Reputation: 1972
Given the following struct:
struct A {
template<typename T, std::size_t N>
A(T const(&array)[N]) {}
template<typename T, std::size_t N>
A& operator=(T const(&array)[N]) { return *this; }
};
The code:
// a is of type A
a = {1, 2, 3, 4};
compiles just fine, since std::initialiser_list
is implicitly converted to an array reference.
However,
A a {1, 2, 3, 4};
A a = {1, 2, 3, 4};
fails to compile with both Clang and GCC. It does compile when I add a constructor that accepts a std::initialiser_list<T>
.
What am I missing?
Upvotes: 1
Views: 63
Reputation: 302718
You just need extra braces or parens:
A a{{1, 2, 3, 4}}; // ok
A b({1, 2, 3, 4}); // ok
The reason for this is the outer braces/parens are for the A
and in the inner braces are for the array
object that you're list-initializing.
With assignment, you don't need the extra parens or braces because they're simply implied by the function call:
a = {1, 2, 3, 4};
is equivalent to:
a.operator=({1, 2, 3, 4});
More or less.
It does compile when I add a constructor that accepts a
std::initialiser_list<T>
.
To elaborate on how list-initialization works. When you write A a{1, 2, 3, 4}
, we're looking first for some std::initializer_list<T>
constructor (which we don't have yet, and so don't find one) and then look for a constructor that we can call with four arguments (which doesn't exist). Adding the extra ()
s or {}
s means we're looking for a constructor that we can call with one argument which we initialize with 1, 2 ,3, 4
.
Once you add the std::initializer_list<T>
constructor, now that's a viable candidate for that first phase of initialization.
Note that this:
compiles just fine, since
std::initialiser_list
is implicitly converted to an array reference.
is not right. There is no std::initializer_list
anywhere in this question. {1, 2, 3, 4}
is a funny thing in C++. It doesn't have a type or anything. It's just a braced-init-list. It's only based on context that we give it meaning. In this case, it's not a thing that's converted to a different thing... it's just a collection of initializers for the array.
Upvotes: 2