Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why variadic function can't "eat" the list-initialization argument in C++11?

The sample code is:

#include <unordered_map>

int main() {
    std::unordered_map<int, std::pair<int, int>> map;

    map.emplace(1, {1, 1});

    return 0;
}

Where the emplace() has signature, like:

template <class... _Args>
pair<iterator, bool> emplace(_Args&&... __args);

The gcc says that function expectes 0 arguments - 2 provided. The clang says that function expects 1 argument - 2 provided.

I don't even understand - what the problem is with this code?

like image 792
abyss.7 Avatar asked Jun 15 '14 12:06

abyss.7


2 Answers

The problem is that {1, 1} is not an expression and has no type. Since it has no type, it cannot be deduced into the template argument list. Neither of them are correct, because the issue has nothing to do with the number of arguments provided.

like image 70
Puppy Avatar answered Sep 28 '22 10:09

Puppy


I don't even understand - what the problem is with this code?

For some obscure reason, an initializer-list argument is a non-deduced context, see initializer_list and template type deduction. This is because § 14.8.2.5/5 of the C++11 standard says so. I don't know the rationale for this seemingly inconsistent and counterintuitive behavior either but we are not alone:

  • 1564. Template argument deduction from an initializer list

  • C++ Type Deduction and Why You Care by Scott Meyers, starting from 37:00

  • If braced initializers have no type, why is the committee so insistent on deducing one for them?

As for your situation, perhaps the easiest fix is:

map.emplace(1, std::make_pair(1, 1));
like image 45
Ali Avatar answered Sep 28 '22 08:09

Ali