Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
448 views
Welcome To Ask or Share your Answers For Others

1 Answer

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...