Reputation: 9753
The following code does not compile with either Visual Studio2017 or online GDB. I expected it to compile as iterator is just a class with types and it is inherited from publicly. Is this not allowed or doesnt this work in VS2017?
template<typename T>
struct Gen : public std::iterator<std::input_iterator_tag, T>
{
T value;
};
int main()
{
Gen<int> g = Gen<int>{ 10 }; // this doesnt
Gen<int> g2 = Gen<int>{ {}, 10 }; // neither does this
}
The error is
Error C2440 'initializing': cannot convert from 'initializer list' to 'Gen'
Upvotes: 10
Views: 3168
Reputation: 40110
What
Gen<int> g = Gen<int>{ 10 };
tries to do is calling the non-existent Gen<int>(int)
constructor. What you want to do is aggregate initialization whose syntax is:
Gen<int> g = { {}, 10 };
And only works since C++17 for derived types:
If the initializer clause is a nested braced-init-list (which is not an expression), the corresponding array element/class member /public base (since C++17) is list-initialized from that clause: aggregate initialization is recursive.
For more information, aggregate initialization is defined in the following standard sections.
[dcl.init.list]/3
- List-initialization of an object or reference of type T is defined as follows:
3.1 If the braced-init-list contains a designated-initializer-list, T shall be an aggregate class.
and
[dcl.init.aggr]/1
An aggregate is an array or a class (Clause 12) with
1.1 no user-provided, explicit, or inherited constructors (15.1),
1.2 no private or protected non-static data members (Clause 14),
1.3 no virtual functions (13.3), and
1.4 no virtual, private, or protected base classes (13.1).
Because in inherits from std::iterator<std::input_iterator_tag, T>
.
Upvotes: 14