【发布时间】:2018-04-13 15:55:08
【问题描述】:
我想为 B 类的构造函数做一个包装器。
由于 B 类的某些部分是可替换的,因此我将这些部分的每个实现分组到几个 A 类中。
我使用完美转发来提供 A 的默认实现来构造 B。
问题是包装器不起作用。如何解决这个问题?
谢谢。
以下也是https://godbolt.org/g/AWwtbf
template<typename T>
class A {
public:
A() { _x = 2; }
int _x;
};
template<typename T, typename C=A<T> >
class B {
public:
explicit B(T x, C&& a = A<T>())
: _x(x), _a(a) {
}
T _x;
A<T>& _a;
};
template<typename T, typename C=A<T> >
B<T, A<T>> make_b(T x, C&& c = A<T>()) {
return B<int, A<int>>(x, c);
};
int main() {
B<int, A<int>> b1(1); // this works.
auto b2 = make_b(1); // this doesn't
}
错误:
error: cannot bind rvalue reference of type 'A<int>&&' to lvalue of type 'A<int>'
return B<int, A<int>>(x, c);
【问题讨论】:
-
阅读this。你似乎有一些基本的误解
-
阅读第1页和第2页后,我认为
A<T>()是一个右值。它代表调用A的构造函数而不是实际的结果,它是A的一个实例。如果A有一个移动构造函数,它接受这个右值并创建A的实际实例,并将B::_a的类型更改为A<T>而不是A<T>&,就可以了吗? -
这听起来太复杂了。 B 和 A 将同时创建。我只会要求 B 有一个 A 作为属性。也许还可以公开
B::_a。这样,创建 B 也会创建 A,但我可以灵活选择创建哪种 A。 -
你应该继续阅读,如果你打算用 C++ 做任何严肃的事情,这将是值得的。每个表达式都有一个值类别,它是左值或右值。
A<T>()确实是一个右值(它的值类别),也是一个A<T>(它的类型)。这是完美转发的基础,但只是故事的一半。
标签: c++ constructor wrapper perfect-forwarding