Let we have a class with n fields. Each field can be moved. So do we have to explicitly define 2^n constructors?
The example with n=2:
struct A{
std::vector<B> a;
std::shared_ptr<B> b;
A(std::vector<B> &a, std::shared_ptr<B> &b):a(a),b(b){};
A(std::vector<B> &a, std::shared_ptr<B> &&b):a(a),b(std::move(b)){};
A(std::vector<B> &&a, std::shared_ptr<B> &b):a(std::move(a)),b(b){};
A(std::vector<B> &&a, std::shared_ptr<B> &&b):a(std::move(a)),b(std::move(b)){};
};
....
A aaa({{},{}}, shared_ptr<B>(new B()));
std::shared_ptr<B> b = ....;
A bbb({{},{}}, b);
You can work around it by having a perfect-forwarding template constructor:
struct A {
std::vector<B> a;
std::shared_ptr<B> b;
template <typename AA, typename BB> A(AA&& a, BB&& b) :
a(std::forward<AA>(a)), b(std::forward<BB>(b)) { }
};
If you need stricter parameter types requirement, you can also add enable_if or static_assert.
Here's a little explanation how perfect forwarding works:
void func1(int&&) { }
template <typename A> void func2(A&& t) {
func3(t);
func4(std::forward<A>(t);
}
template <typename B> void func3(B&&) { }
template <typename C> void func4(C&&) { }
int foo;
const int bar;
func1(foo); // ERROR
func1(bar); // ERROR
func1(std::move(foo)); // OK
func2(foo); // OK, A = int&, B = int&, C = int&
func2(bar); // OK, A = const int&, B = const int&, C = const int&
func2(std::move(foo)); // OK, A = int&&, B = int&, C = int&& <- note how && collapses to & without std::forward
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