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

2

14

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?

Claudication answered 15/6, 2014 at 12:27 Comment(0)
A
12

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.

Arnulfoarny answered 15/6, 2014 at 12:32 Comment(2)
@Jefffrey: No, {...} is not an expression. The first is a special-casing for auto-deduction which should really never have been there (and will hopefully be removed sometime in the future), and the second one is just construction from braced-init-list.Grabowski
@Massa: Yes, that would be sufficient.Arnulfoarny
M
7

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:

As for your situation, perhaps the easiest fix is:

map.emplace(1, std::make_pair(1, 1));
Maximilian answered 15/6, 2014 at 13:8 Comment(5)
The reason is not obscure - tell me, what kind of initializer_list should {1, "hi"} be?Grabowski
@Grabowski I don't get your example. auto x = { 1, "hi" }; is also a compile time error, so what is the point you are trying to make?Maximilian
@Grabowski I guess the reason, if any, must be something else. My guess is that allowing this kind of deduction on function template arguments, could backfire. Although, I failed to come up with an example.Maximilian
The problem is that auto x = {1, 1}; is allowed at all. It's a special case in the standard, and it's an unnecessary hack that should be removed. :/Grabowski
@Grabowski I guess it is too late to change that, that would be break a lot of code. But do you see any corner case in which deducing initializer_list for a function template argument could backfire?Maximilian

© 2022 - 2024 — McMap. All rights reserved.