【问题标题】:function template overload with rvaule reference as argument does not work?以 rvaule 引用作为参数的函数模板重载不起作用?
【发布时间】:2021-07-06 21:52:27
【问题描述】:

当输入不是右值时,以 && 作为参数的函数模板似乎无法重载。以here为例:

template<typename A, typename B>
void test_tp_func(A&& a, B&& b)
{
    std::cout<<"tp1(" << a << "," << b << ")\n";
}
template<typename A>
void test_tp_func(A&& a, int&& b)
{
    std::cout<<"tp2(" << a << "," << b << ")\n";
}
int main()
{
    test_tp_func(1, 2);
    int i{10};
    const int& ir = i;
    test_tp_func(2, ir);
    test_tp_func(2, std::move(i));
}

输出是:

tp2(1,2)
tp1(2,10)
tp2(2,10)

我们可以看到test_tp_func(2, ir); 根本没有使用重载。如何确保它使用test_tp_func(A&amp;&amp; a, int&amp;&amp; b)?一种方法是添加 enable_if_t 以在 B 为 int 时禁用原始模板。但是,原始模板 test_tp_func(A&amp;&amp; a, B&amp;&amp; b) 是在一个不受我控制的文件中定义的。

更新了示例以实际使用 const&

【问题讨论】:

    标签: c++ c++17


    【解决方案1】:

    如何选择右值重载?如果参数是 rvaluei 不是,这将有所帮助。

    它不是纯右值(它是一个命名变量),也不是一个 xvalue。

    如果你只是想拦截B = int的情况,为什么不直接将参数类型设为int呢?使用int&amp;&amp; 只会根据定义匹配右值。

    正如 cmets 中所讨论的,您不能简单地将转发引用 B&amp;&amp; 替换为右值引用 int&amp;&amp;(或任何其他代替 int 的具体类型),因为转发引用在参数推导期间得到特殊处理 (请参阅here 并搜索“转发参考”,这是一种特殊情况。

    您需要两个重载:const ref const int&amp; 和 rvalue ref int&amp;&amp;,以涵盖与原始转发引用相同的情况。

    【讨论】:

    • 另一种选择是创建int&amp;const int&amp;int&amp;&amp; 重载 - 如果在非const 情况下需要对传递的参数进行一些操作。
    • int 只是一个例子。现实世界的案例,B 可以是一个大类,副本对它来说是昂贵的。按值传递是不可接受的。它应该是 const& 或 &&
    • 绝对正确。我怀疑这里OP只是执行了手动替换,没有意识到右值引用和转发引用之间的区别。
    • 在这种情况下,您确实需要编写&amp;&amp; 右值引用和const&amp; const ref 重载。他们做不同的事情,并匹配不同的论点。 B&amp;&amp; 转发引用在参数推断期间得到特殊处理以处理两者。
    • 似乎是这样。这有点烦人。我认为既然 B&& 可以处理 const B& 和 B&& 那么 int&& 应该用于重载 const int& 和 int&&。但不幸的是,事实并非如此。这里有什么解释吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-10
    相关资源
    最近更新 更多