我用CRTP(奇怪的递归模板模式)测试了std :: forward。 但是我无法将左值传递给它。请阅读以下代码。
#include <algorithm>
struct DataClassA {};
template <typename Derived>
struct ContainerCRTP {
template <typename Element>
void add(Element&& tag) { }
};
struct Container : public ContainerCRTP<Container> { };
int main()
{
DataClassA data_a;
Container container;
// Case 1: passing lvalue. compile error.
container.add<DataClassA>(data_a);
// Case 2: passing rvalue. It succeeds compiling.
container.add<DataClassA>(std::move(data_a));
}
当我在案例1中传递左值时,gcc编译器给我一个编译错误,
template argument deduction/substitution failed:
cannot convert ‘data_a’ (type ‘DataClassA’) to type ‘DataClassA&&’
另一方面,当我在案例2中传递rvalue时,gcc编译器不会给我编译错误。
如何为container.add<DataClassA>(data_a)
提供左值?
答案 0 :(得分:3)
致电时:
container.add<DataClassA>(data_a);
// ^^^^^^^^^^^
显式提供模板参数意味着编译器不会推导出模板参数(即,您没有获得转发引用行为)。
使用add
作为模板参数实例化DataClassA
意味着其签名为:
void add(DataClassA&& tag)
这是一个右值引用,而不是转发引用,因此左值参数不能绑定到它。
要使用完美转发,必须让编译器从参数中推导出模板参数。基于参数的值类别,有三种可能的推论(T
,T&
,T&&
),这就是std::forward
再现参数的值类别的方式:< / p>
container.add(data_a);