当基类型为函数引用时,右值引用重载
Rvalue reference overloading when base type is function reference
我有一个类似的类,应该接受一个函数对象并稍后使用它:
template<typename F>
class A {
public:
A(const F& f) : _f(f) {}
A(F&& f) : _f(std::move(f)) {}
private:
F _f;
};
我还定义了一个方便的初始化函数和一个虚拟测试函数:
template<typename F>
A<F> MakeA(F&& f) {
return A<F>(std::forward<F>(f));
}
void foo() {}
我得到一个错误,它是不可能重载A<F>::A(F&&)
与A<F>::A(const F&)
为F = void(&)()
时,我调用:
auto a = MakeA(foo);
我明白我可以通过使用函数指针而不是函数引用来修复它,并且lambda也可以很好地工作:
auto a1 = MakeA(&foo);
auto a2 = MakeA([]{});
函数引用有什么特别之处,为什么重载不起作用?
clang的错误消息更有启发性:
6:错误:多个'A'的重载实例化为同一个签名'void (void (&&)())'
这是因为对于任何左值引用类型T = U&
, T&&
和T const&
是相同的类型,根据[dcl.ref]:
6 -如果[…]类型TR[是]对类型T的引用,尝试创建类型"对cv TR的左值引用"会创建类型"对T的左值引用",而尝试创建类型"对cv TR的右值引用"会创建类型TR[…]
using T = int&;
static_assert(std::is_same<T&&, T const&>::value, "!!");
真正的问题是你在适用范围之外应用了"通用引用/std::forward
"模式;它只适用于参数的完美转发。如果传递lambda左值
auto l = []{};
auto d = MakeA(l); // breaks
编写类型推导构造函数的正确方法是将decay
应用于实参的类型(参见make_optional
):
template<typename F>
A<typename std::decay<F>::type> MakeA(F&& f) {
return A<typename std::decay<F>::type>(std::forward<F>(f));
}
与F = void(&)()
, F&&
和const F&
是相同的类型,因此错误。
相关文章:
- 取消引用运算符不能重载
- 错误:无法解析对重载函数的引用;你的意思是调用它吗?
- 传递空初始值设定项列表时使用右值和左值引用候选项的重载解析
- 为什么我的运算符 + 重载尽管是通过引用传递的,但仍调用我的复制构造函数?
- C++编程:运算符重载中的引用如何工作?
- 重载运算符*以获取对另一个类的实例的引用
- 对运算符=使用通用引用,而不是多个重载
- 如何重载下标运算符 [] 以引用 2d STL 数组?
- 具有参数包和通用引用的重载选择
- 有什么理由用右值引用重载运算符吗?
- 封装 ublas 并将常量引用重载到 operator()
- std::forward() 的右值引用重载的目的是什么?
- std::move into static_pointer_cast:为什么static_pointer_cast没有右值引用重载?
- 通过引用重载多个函数对象
- C++ 右值引用重载,而不是移动构造函数
- 通过引用重载运算符-C++来传递对象
- 指针和引用 + 重载运算符
- 当基类型为函数引用时,右值引用重载
- 在没有歧义的情况下,是否允许通过引用重载函数
- 是否需要为const和通用引用重载?