c++ - 当左值引用参数和右值引用参数作为相同的转发引用类型传递时,为什么它不起作用?

标签 c++ c++11 templates overloading forwarding-reference

#include <type_traits>

template<typename T>
void f(T&& a, T&& b)
{}

int main()
{
    int n;
    f(n, std::move(n));
}

T&&是转发引用类型,所以我觉得decltype(a)应该是int&decltype(b) 应该是 int&&

但是,上面的代码会产生以下错误:

main.cpp(13,2): error : no matching function for call to 'f' f(n, std::move(n));

main.cpp(7,6): note: candidate template ignored: deduced conflicting types for parameter 'T' ('int &' vs. 'int')

void f(T&& a, T&& b)

1 error generated.

当左值引用参数和右值引用参数作为相同的转发引用类型传递时,为什么它不起作用?

我的编译器是 clang 4.0。

最佳答案

编译器错误非常直接,T 不能同时在 int&int 中推导。为了让它工作,你必须提供一个额外的模板参数:

template<typename T1, typename T2>
void f(T1&& a, T2&& b)
{}

推理

在处理 forwarding references 时,模板参数推导遵循特殊规则(又名通用引用)基于 reference collapsing rules

  • 你&&变成你&
  • 你& && 变成你&
  • U&& & 变成 U&
  • U&& && 变成 U&&

例如,如果你有一个函数模板:

template<typename T>
void foo(T&&) {}
  1. 如果foo 输入是U 类型的左值,T 将减去U&。遵循上面的引用折叠规则,参数类型将变为 U&
  2. 如果 foo 输入是 U 类型的右值,T 将被扣除为 U,因此参数类型将为 U&&

现在按照上面的推理,模板参数推导会将 T 推导为 int& 作为您的第一个参数,因为输入是一个 lvalue

模板参数推导将尝试匹配第二个参数的类型,但对于第二个参数,因为输入是遵循上述规则的右值 T 将被推导为 int .

此时编译器举起双手尖叫“dude T 的推导类型必须匹配所有输入参数”。

关于c++ - 当左值引用参数和右值引用参数作为相同的转发引用类型传递时,为什么它不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42410809/

相关文章:

C++如何仅在没有其他人直接或间接引用该指针时删除对象指针

c++ - 引用变量是否在堆栈中占用内存?

c++ - 比较 std::function<>

C++ 异步线程在调用线程完成时终止

c++ - 在 Windows 和 Linux 之间通过 C++ 套接字发送 float 组

c++ - std::function 和 std::packaged_task 转换

c++ - 如何通过 `friend` 将流运算符<<放在模板化类主体之外?

node.js - 从字符串渲染哈巴狗模板?

c++ - 模板参数中的 const

c++ - 如何在 Windows 上有效使用 PortAudio Pa_OpenStream()?