I have 2 classes:
template<typename T>
class base{
T t;
public:
base(base &&b): t(std::move(b.t)){}
};
template<typename T, typename T2>
class derived : protected base<T>{
T2 t2;
public:
derived(derived &&d): base<T>(std::move(d)), t2(std::move(d.t2)){}
};
I move entire d object in the derived move-constructor to initialize base part and d becomes invalid but I still need it to use it's part for t2 initialization
Is it possible to do such a thing?
I would say that your construct is correct except for a little syntax error, you need to qualify base<T> in the initializer list:
derived(derived &&d): base<T>(std::move(d)), t2(std::move(d.t2)){}
First, the order of initialization is independant of the order of the initializer list. Draft n4296 says in 12.6.2 Initializing bases and members [class.base.init] § 13
In a non-delegating constructor, initialization proceeds in the following order:
(13.1) — First, and only for the constructor of the most derived class (1.8), virtual base classes are initialized in
the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes,
where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
(13.2) — Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list
(regardless of the order of the mem-initializers).
(13.3) — Then, non-static data members are initialized in the order they were declared in the class definition
(again regardless of the order of the mem-initializers).
(13.4) — Finally, the compound-statement of the constructor body is executed.
[ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the
reverse order of initialization. —end note ]
We have also §7 or same chapter that says:
The initialization performed by each mem-initializer constitutes a full-expression. Any
expression in a mem-initializer is evaluated as part of the full-expression that performs the initialization.
My understanding is that standard says that in the move ctor for the derived class, things happens in that order:
move ctor for base class is called
in turn it calls move ctor for T effectively constructing t member of target and eventually zeroing t member of source
move ctor for T2 object is called - at that moment, the end of the full expression has not been reached, and only t member of source has eventually been destroyed
at the end of the full statement, source object is left in an undetermined state and should no longer be used.
Related
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 Initialization shall proceed in the
following order:
— First, and only for
the constructor of the most derived
class as described below, virtual base
classes shall be initialized in the
order they appear on a depth-first
left-to-right traversal of the
directed acyclic graph of base
classes, where “left-to-right” is the
order of appearance of the base class
names in the derived class
base-specifier-list.
— Then, direct
base classes shall be initialized in
declaration order as they appear in
the base-specifier-list (regardless of
the order of the mem-initializers).
— Then, nonstatic data members shall be
initialized in the order they were
declared in the class definition
(again regardless of the order of the
mem-initializers).
— Finally, the body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 Initialization shall proceed in the
following order:
— First, and only for
the constructor of the most derived
class as described below, virtual base
classes shall be initialized in the
order they appear on a depth-first
left-to-right traversal of the
directed acyclic graph of base
classes, where “left-to-right” is the
order of appearance of the base class
names in the derived class
base-specifier-list.
— Then, direct
base classes shall be initialized in
declaration order as they appear in
the base-specifier-list (regardless of
the order of the mem-initializers).
— Then, nonstatic data members shall be
initialized in the order they were
declared in the class definition
(again regardless of the order of the
mem-initializers).
— Finally, the body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 Initialization shall proceed in the
following order:
— First, and only for
the constructor of the most derived
class as described below, virtual base
classes shall be initialized in the
order they appear on a depth-first
left-to-right traversal of the
directed acyclic graph of base
classes, where “left-to-right” is the
order of appearance of the base class
names in the derived class
base-specifier-list.
— Then, direct
base classes shall be initialized in
declaration order as they appear in
the base-specifier-list (regardless of
the order of the mem-initializers).
— Then, nonstatic data members shall be
initialized in the order they were
declared in the class definition
(again regardless of the order of the
mem-initializers).
— Finally, the body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 Initialization shall proceed in the
following order:
— First, and only for
the constructor of the most derived
class as described below, virtual base
classes shall be initialized in the
order they appear on a depth-first
left-to-right traversal of the
directed acyclic graph of base
classes, where “left-to-right” is the
order of appearance of the base class
names in the derived class
base-specifier-list.
— Then, direct
base classes shall be initialized in
declaration order as they appear in
the base-specifier-list (regardless of
the order of the mem-initializers).
— Then, nonstatic data members shall be
initialized in the order they were
declared in the class definition
(again regardless of the order of the
mem-initializers).
— Finally, the body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 Initialization shall proceed in the
following order:
— First, and only for
the constructor of the most derived
class as described below, virtual base
classes shall be initialized in the
order they appear on a depth-first
left-to-right traversal of the
directed acyclic graph of base
classes, where “left-to-right” is the
order of appearance of the base class
names in the derived class
base-specifier-list.
— Then, direct
base classes shall be initialized in
declaration order as they appear in
the base-specifier-list (regardless of
the order of the mem-initializers).
— Then, nonstatic data members shall be
initialized in the order they were
declared in the class definition
(again regardless of the order of the
mem-initializers).
— Finally, the body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.