【问题标题】:Incorrect understanding of implicit conversion from reference to std::reference_wrapper or compiler bug?对从引用到 std::reference_wrapper 或编译器错误的隐式转换理解不正确?
【发布时间】:2017-08-16 13:56:51
【问题描述】:

我对一些涉及引用和 std::reference_wrapper 的代码感到困惑,我完全不清楚这是否是我的错,因为我误解了引用包装器的工作原理,或者我是否遇到了编译器错误。

我有一个简单的映射,将一个对象的引用从一个复杂的类配对到一个值:

std::unordered_map<Object const &obj, int32_t value> myMap;

(为简单起见,我明确省略了映射编译所需的哈希和相等函子)

由于我不能直接使用地图中的引用,所以我使用了引用包装器:

std::unordered_map<std::reference_wrapper<const Object> obj, int32_t value> myMap;

现在,我的地图被填充到一个函数中,例如:

void myFunction(Object const &obj, int32_t value)
{
    ...
    myMap.emplace(std::make_pair(obj, value));
}

但该代码虽然可以编译,但不起作用。但是,这个按预期工作:

void myFunction(Object const &obj, int32_t value)
{
    ...
    myMap.emplace(std::pair<std::reference_wrapper<const Object>, int32_t>(obj, value));
}

(请注意,在第二个版本中,我仍然没有明确构建 obj 的引用包装器)

所以,我的疑问是:

我对引用包装器的使用有误解吗?没有从引用到reference_wrapper 的隐式转换?如果不是,为什么代码首先编译?

或者这是 std::make_pair 中的一个已知问题/缺陷无法正确扣除传递给它的类型?

【问题讨论】:

    标签: c++ reference implicit-conversion reference-wrapper


    【解决方案1】:

    std::make_pair never(1) 将引用类型推断为该对中的类型之一,它总是产生值类型。所以对emplace 的调用接收一个临时 std::pair&lt;Object, int32_t&gt; 作为参数。然后引用包装器从这个临时初始化,这意味着它将绑定到这个 temporary 对的 first 成员。

    在第二种情况下,临时是std::pair&lt;std::reference_wrapper&lt;const Object&gt;, int32_t&gt; 类型(因为您已经明确要求了),这意味着临时对中有一个引用包装器,直接绑定到obj。然后从这个临时引用包装器中复制映射内的引用包装器,因此直接引用obj

    (1) “从不”在这里不是真的。有一个例外:当std::make_pair 的参数之一是std::reference_wrapper&lt;T&gt; 类型时,该对中的类型将被删除为T&amp;。这实际上为您提供了正确的解决方案:将obj 包装在std::cref 中的make_pair 调用中:

    myMap.emplace(std::make_pair(std::cref(obj), value));
    

    这将导致临时对包含一个引用,并且映射内的 reference_wrapper 将绑定到它的引用对象 (obj),这正是您想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-06
      • 1970-01-01
      相关资源
      最近更新 更多