gpt4 book ai didi

c++ - 基类型为函数引用时右值引用重载

转载 作者:太空狗 更新时间:2023-10-29 20:40:20 25 4
gpt4 key购买 nike

我有一个类似于此的类,它应该接受一个函数对象并在以后使用它:

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([]{});

函数引用有什么特别之处,为什么重载在那里不起作用?

Test code here.

最佳答案

来自 clang 的错误消息更具启发性:

6 : error: multiple overloads of 'A' instantiate to the same signature 'void (void (&&)())'

这是因为对于任何左值引用类型T = U&T&&T const&是相同的类型,根据 [dcl.ref] 中的引用折叠规则:

6 - If [...] a type TR [is] a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type “lvalue reference to T”, while an attempt to create the type “rvalue reference to cv TR” creates the type 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));
}

关于c++ - 基类型为函数引用时右值引用重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24549008/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com