rvalue参数的模板类型推导

bol*_*lov 4 c++ templates overloading rvalue c++11

我理解C++ 11中的转发方法.

template <class T> void foo(T &&)
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

如果我foo使用A < int > &(左值)对象调用foo(T &&),它将调用,而不是foo(A < T > &&).在定义中foo(T &&obj),我设法区分std和自定义特征,如果objA<T>,但是这会产生非常混乱的代码,因为我必须A从中调用方法obj,并且obj被声明为T,而不是A < T >.重新排序声明或添加左值重载不能解决问题.

希望我能让自己明白.我提供了一个简化的代码,以便解决问题.我实现一个自定义Optional < T >类(类似boost::optional)和我在构造函数这个问题,因为我需要能够创建(并分配)一个Optional < T >从另一个对象Optional < T >,Optional < U >,TU对象.(T由要创建的可选对象保存的类型在哪里,U是不同的类型,可转换为T).

感谢您的时间.

dyp*_*dyp 6

在函数调用的模板参数推导期间,"通用引用"的特殊规则仅在参数类型为cv-unqualified模板参数[temp.deduct.call]/3时适用.

[ P是函数模板的参数类型,是参数的类型A]

如果P是对cv-unqualified模板参数的rvalue引用,并且参数是左值,则使用类型"左值引用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
Run Code Online (Sandbox Code Playgroud)

- 结束例子 ]

同样,这些规则并不适用于参数类型A<T>&&.它不是"通用参考",而是纯粹的右值参考类型.


如果你想在两个构造函数之间进行排名,其中A<T>-version应该更专业(更好的匹配),你可以:

  • 提供2个三个重载A<T> const&,A<T>&(感谢,埃里克Niebler)和A<T>&&T&&通用版
  • 使用SFINAE; 使用参数提供两个重载T&&并检查是否T是特化A<T>