右值参数的模板类型推断
Template type deduction for rvalue arguments
我了解 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;
}
如果我使用 A < int > &
(左值)对象调用foo
,它将调用 foo(T &&)
,而不是 foo(A < T > &&)
。在foo(T &&obj)
的定义中,我设法用 std 和自定义特征来区分obj
是否A<T>
,但这会产生非常非常混乱的代码,因为我必须从 obj
调用 A
方法,并且obj
被声明为 T
,而不是 A < T >
。重新排序声明或添加左值重载并不能解决问题。
希望我能理解自己。我提供了一个简化的代码,以便在问题中分区。我正在实现一个自定义Optional < T >
类(类似于boost::optional
),我在构造函数中遇到了这个问题,因为我需要能够从另一个Optional < T >
、Optional < U >
、T
或U
对象创建(和分配)一个Optional < T >
对象。(其中T
是要创建的可选对象持有的类型,U
是可转换为T
的不同类型)。
谢谢你的时间。
在函数调用的模板参数推导期间,"通用引用"的特殊规则仅在参数类型为 cv 非限定模板参数 [temp.deduct.call]/3 时适用
[ P
是函数模板的参数类型,A
是参数的类型]
如果
P
是对 cv 非限定模板参数的右值引用,并且参数是左值,则使用类型"对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>
-version 应该更专业(更好的匹配),你可以:
- 除了
T&&
通用版本外,还提供两个三个重载A<T> const&
、A<T>&
(感谢 Eric Niebler)和A<T>&&
- 使用 SFINAE;提供两个带有参数
T&&
的重载,并检查T
是否是A<T>
的专用化
- 检查函数返回类型是否与STL容器类型值相同
- boost 是否有按特殊类型值编码状态"compact optional"?
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 错误:"模板<类_Tp,类_Dp>类 std::unique_ptr"的模板参数列表中参数 1 的类型/值不匹配
- 类型名称 T::类型::值中的预期非限定 id
- 提升不良词法强制转换:将字符串转换为无符号长整型时,无法将源类型值解释为目标
- 在一行中将默认类型值上的指针作为参数传递
- 为什么乘法与C++双精度类型值的加法一样快?
- 模板参数列表中参数 3 处的类型/值不匹配
- 我预测char数组类型值只能投射指针类型
- 模板-模板参数给出神秘的类型/值不匹配
- 为什么q_enum在没有qregistermetatepe的情况下无法获得正确的类型值
- 类型值不能用于初始化类型实体
- 类模板方法的专用化,类型名称是类模板 - 错误:参数处的类型/值不匹配
- C++ 可变参数模板和模板模板参数:错误:模板参数列表中参数 1 处的类型/值不匹配
- 用于存储多种类型值的 STL 容器
- 如何在尝试为某些非类型值实例化模板子类方法时产生编译器错误
- 穿越拥有两种类型值的BST
- C++字符类型值由OS定义
- 使用函数返回值作为默认模板非类型形参