5

I have following template function:

template<typename T> void foo2(T t) {}

I know that I cannot call it using:

foo2({1,2,3});

because initializer list is a non deduced context for a template argument. I have to use:

foo2<std::initializer_list<int>>({1,2,3});

but I can also use:

foo2(std::initializer_list<int>({1,2,3}));

which makes me wonder what is the difference between: {1,2,3} and std::initializer_list<int>({1,2,3})?

mike
  • 1,670
  • 11
  • 21
  • 10
    `std::initializer_list({1,2,3})` is an expression of type `std::initializer_list`. `{1,2,3}` is not an expression. Braced list can only occur in contexts that the language definition explicitly allows it, not just anywhere that an expression can occur. – M.M Jan 13 '17 at 13:07
  • 2
    @M.M When you know an answer to a question with 0 answers, but then, it turns out it's answered in the comments. ﴾ ͡° ʖ̯ ͡°﴿ – luk32 Jan 13 '17 at 13:19
  • 2
    @luk32 feel free to write an answer ... i think a full answer should cover the details of the template which I'm not so sure about – M.M Jan 13 '17 at 13:21
  • related/dupe: http://stackoverflow.com/questions/17582667/why-do-auto-and-template-type-deduction-differ-for-braced-initializers – NathanOliver Jan 13 '17 at 13:23

1 Answers1

8

A braced-init list isn't an expression, and thus doesn't have a type. When you call

foo2({1,2,3});

the compiler doesn't know what type {1,2,3} represents in your mind, and so it doesn't compile.

foo2<std::initializer_list<int>>({1,2,3});

compiles because here the compiler doesn't have to deduce the type, you have specified it, it is std::initializer_list<int>. So it can initialize t with {1,2,3}.

The third call also compiles because the compiler can deduce the type. std::initializer_list<int>({1,2,3}) is obviously a std::initializer_list<int>, and so it can initialize t with the passed prvalue.

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
  • 2
    Note that in C++17 the "guaranteed elision" rules make your last paragraph different. In a sense, there is no longer a value created there then elided to the function argument; it just becomes a way to initialize the function argument. Or so I gather, I've yet to master the new rules. (In practice, there is next to no difference in this case) – Yakk - Adam Nevraumont Jan 13 '17 at 14:09