我理解C ++ 11中的转发方法。
template <class T> void foo(T &&)
foo现在接受左值和左值。
我的问题是当我进一步超载foo时。 考虑一下这个简单的代码:
template <class T> class A {};
template <class T> void foo(T &&obj) {}
template <class T> void foo(A<T> &&obj) {}
int main() {
int i;
A<int> a;
foo(i); // calls foo(T &&) as I want
foo(a); // calls foo(T &&), but I want it to call foo(A<T> &&)
return 0;
}
如果我使用foo
(左值)对象致电A < int > &
,则会调用foo(T &&)
,而不是foo(A < T > &&)
。在foo(T &&obj)
的定义中,如果obj
是A<T>
,我设法区分std和自定义特征,但这会产生非常混乱的代码,因为我必须调用{{1}来自A
的方法,obj
被声明为obj
,而不是T
。
重新排序声明或添加左值重载并不能解决问题。
希望我让自己明白了。
我提供了一个简化的代码,以便解决问题。
我正在实现一个自定义A < T >
类(类似于Optional < T >
),我在构造函数中遇到此问题,因为我需要能够从另一个{{boost::optional
创建一个Optional < T >
对象1}},Optional < T >
,Optional < U >
或T
对象。 (其中U
是要创建的可选对象所持有的类型,T
是不同的类型,可转换为U
)。
感谢您的时间。
答案 0 :(得分:6)
在函数调用的模板参数推导期间,“通用引用”的特殊规则仅在参数类型为cv-unqualified模板参数[temp.deduct.call] / 3
时适用。 [P
是函数模板的参数类型,A
是参数的类型]
如果
P
是对cv-nonqualified模板参数的右值引用,并且参数是左值,则使用“A
的左值引用”代替A
类型扣除。 [示例:的template <class T> int f(T&&); template <class T> int g(const T&&); int i; int n1 = f(i); // calls f<int&>(int&) int n2 = f(0); // calls f<int>(int&&) int n3 = g(i); // error: would call g<int>(const int&&), which // would bind an rvalue reference to an lvalue
- 结束示例]
同样,这些规则不适用于参数类型A<T>&&
。它不是“通用参考”,而是纯粹的右值参考类型。
如果你想在两个构造函数之间进行排名,A<T>
- 版本应该更专业(更好的匹配),你可以:
A<T> const&
通用之外,A<T>&
,A<T>&&
(谢谢,Eric Niebler)和T&&
版本T&&
提供两个重载并检查T
是否为A<T>