Reputation: 13713
Am I right in assuming that
class D { /* ... */ };
int f (const D & t) { return /* something calculated from t */; }
template<class T>
class C {
private:
int m_i;
T m_t;
// or first m_t, then m_i -- careless order of declarations
public:
template<class T_>
C (T_ && t) : m_t (std::forward<T_> (t)), m_i (f (t)) {
}
};
C<D> c (D ());
may lead to a bug since the value of t
has been moved away when f(t)
is called? Is there any way to avoid this problem apart from (i) using a factory function or (ii) introducing a dependency on the order in which m_i
and m_t
are declared?
Upvotes: 1
Views: 1211
Reputation: 208333
The first thing is that the order of evaluation of the initializer list is determined by the order of the members in the class definition, so in your case, it will be:
template<class T_>
C (T_ && t)
: m_i (f (t)), m_t (std::forward<T_> (t)) {
}
So in your case it is fine. It would also be fine if you reordered the members so that m_t
is declared before m_i
and you used m_t
in the initialization:
T m_t;
int m_i;
template<class T_>
C (T_ && t)
: m_t (std::forward<T_> (t)), m_i (f (m_t)) {
}
Upvotes: 3
Reputation: 153820
The member m_i
is initialized first and by the time the value is clearly not moved nor will it be moved. When you initialize m_t(std::forward<T>(t))
you implicitly promise that you won't use t
s value (at least, until you have given it a new one).
In general, the order of execution matters and this is true for the member initializer list, too. That is, you need to be careful in which order you declare your members when you introduce dependencies between them.
Upvotes: 2