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'
An aggregate is just what it sounds like: a bunch of things clumped together. This definition includes aggregates of mixed types, like structs and classes. An array is an aggregate of a single type. Initializing aggregates can be error-prone and tedious. C++ aggregate initialization makes it much safer.
The base class members are already initialized by the time your derived-class constructor gets to run. You can assign them, if you have access, or call setters for them, or you can supply values for them to the base class constructor, if there is one suitable.
Formal definition from the C++ standard (C++03 8.5. 1 §1): An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
If we inherit a class from another class and create an object of the derived class, it is clear that the default constructor of the derived class will be invoked but before that the default constructor of all of the base classes will be invoke, i.e the order of invocation is that the base class's default constructor ...
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>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With