完美转发构造函数的包装器
Wrapper for perfect forwarding constructor
我想为 class B.
的构造函数制作一个包装器
由于 class B 的某些部分是可替换的,我将这些部分的每个实现分组为几个 class A。
我使用完美转发为构建B提供了A的默认实现。
问题是包装器不起作用。如何解决这个问题?
谢谢。
以下也在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);
如何完美转发东西?
- 将参数类型设为
template
参数。
- 通过右值引用接受参数 (
&&
)。
std::forward
参数。
你得到了nr。 1 和 2 但忘记了 nr。 3:
template<typename T, typename C=A<T> >
B<T, A<T>> make_b(T x, C&& c = A<T>()) {
return B<T, A<int>>(x, std::forward<C>(c));
};
如何避免悬空引用?
这段代码创建了一个悬空引用,即对已经 gone:
的对象的引用
explicit B(T x, C&& a = A<T>())
: _x(x), _a(a) {
}
T _x;
A<T>& _a;
考虑这里发生的事情:创建了一个临时 A
,右值引用 a
被用在左值表达式 (a
) 中,因此它变成了左值引用并且A& _a
随后愉快地绑定到它。当完整表达式完成时(在第一个 ;
处),临时 A
实例被销毁并且 A& _a
指的是一个不存在的对象。如果在那之后使用 _a
,则行为未定义。
在理解 value categories, object lifetime and reference collapsing 规则之前,避免将引用作为数据成员。
只需按值存储 A
:
explicit B(T x, C&& a = A<T>())
: _x(x), _a(std::move(a)) {
}
T _x;
A<T> _a;
或者在B
之外实例化A
并将其作为左值引用传递:
explicit B(T x, C& a) : _x(x), _a(a) {}
C& _a;
我想为 class B.
的构造函数制作一个包装器由于 class B 的某些部分是可替换的,我将这些部分的每个实现分组为几个 class A。
我使用完美转发为构建B提供了A的默认实现。
问题是包装器不起作用。如何解决这个问题?
谢谢。
以下也在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);
如何完美转发东西?
- 将参数类型设为
template
参数。 - 通过右值引用接受参数 (
&&
)。 std::forward
参数。
你得到了nr。 1 和 2 但忘记了 nr。 3:
template<typename T, typename C=A<T> >
B<T, A<T>> make_b(T x, C&& c = A<T>()) {
return B<T, A<int>>(x, std::forward<C>(c));
};
如何避免悬空引用?
这段代码创建了一个悬空引用,即对已经 gone:
的对象的引用 explicit B(T x, C&& a = A<T>())
: _x(x), _a(a) {
}
T _x;
A<T>& _a;
考虑这里发生的事情:创建了一个临时 A
,右值引用 a
被用在左值表达式 (a
) 中,因此它变成了左值引用并且A& _a
随后愉快地绑定到它。当完整表达式完成时(在第一个 ;
处),临时 A
实例被销毁并且 A& _a
指的是一个不存在的对象。如果在那之后使用 _a
,则行为未定义。
在理解 value categories, object lifetime and reference collapsing 规则之前,避免将引用作为数据成员。
只需按值存储 A
:
explicit B(T x, C&& a = A<T>())
: _x(x), _a(std::move(a)) {
}
T _x;
A<T> _a;
或者在B
之外实例化A
并将其作为左值引用传递:
explicit B(T x, C& a) : _x(x), _a(a) {}
C& _a;