【问题标题】:how can l-values be passed to std::make_pairl 值如何传递给 std::make_pair
【发布时间】:2020-12-05 11:41:45
【问题描述】:

std::make_pairthere is only one implementation C++14 onwards

模板 constexpr std::pair make_pair( T1&& t, T2&& u );

这两个参数都是 R 值引用并根据this

右值引用不能用左值初始化。

    int i = 1;
    char ch = 'a';
    std::unordered_map<int, char> mp;
    mp.insert(make_pair<int,char>(i, ch));

因此,当我尝试在上面的代码中使用 make_pair 时,它会正确抛出错误 error: cannot bind rvalue reference of type 'int&amp;&amp;' to lvalue of type 'int'

但是,如果我更改删除模板参数并将其调用为

,它对于上述代码非常有效
mp.insert(make_pair(i, ch));

我很困惑这是如何工作的,因为 ich 都是 L 值。模板参数解析是否将 L 值转换为 R 值或类似它是如何工作的?

【问题讨论】:

  • 这些不是右值引用——它们是forwarding references。他们接受右值和左值。但是,只有当您明确指定模板参数,但允许模板参数推导完成其工作时,它们才会以这种方式工作。

标签: c++ c++11 templates template-argument-deduction forwarding-reference


【解决方案1】:

make_pair的参数没有声明为右值引用,而是forwarding reference

转发引用是一种特殊的引用,它保留 函数参数的值类别,可以 通过 std::forward 转发它。转发引用是:

  1. 函数模板的函数参数声明为右值 引用相同的 cv 非限定类型模板参数 函数模板:

template argument deduction 的帮助下,转发引用适用于左值和右值。传入左值时,模板参数会被推导出为左值引用,引用折叠后,函数参数也是左值引用。在传递右值时,模板参数会被推断为非引用,函数参数是右值引用。

另一方面,如果您像make_pair&lt;int,char&gt;(...) 一样明确指定模板参数,则函数参数会相应地变为右值引用。

【讨论】:

  • 在代码中:using R = T&amp;; R &amp;&amp;rr 声明为T&amp;,因为&amp; + &amp;&amp; 折叠为&amp;std::make_pair&lt;T&amp;, U&amp;&gt; 和朋友因此选择 (T&amp;, U&amp;),而不是 (T&amp;&amp;, U&amp;&amp;) 或类似的。模板参数推导旨在在使用左值调用时选择该专业化。使用右值调用会选择std::make_pair&lt;T, U&gt;,它确实需要(T&amp;&amp;, U&amp;&amp;)
【解决方案2】:

answer by songyuanyao 已经解释了大部分情况。不过,我想贡献一下如何使用显式模板参数来完成这项工作。您已经走了大部分路,但没有迈出最后一步。

我很困惑这是如何工作的,因为 ich 都是 L 值。

没错。您需要左值,您可以在模板参数中指定:

std::make_pair<int &, char &>(i, ch)

或在更多情况下有效的形式:

std::make_pair<const int &, const char &>(i, ch)

一些额外的写作,但如果参数推导由于某种原因失败,则需要。

【讨论】:

    猜你喜欢
    • 2022-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 2015-12-03
    • 2015-09-17
    • 2015-09-03
    相关资源
    最近更新 更多