【问题标题】:Using std::weak_ptr::lock() in std::tie在 std::tie 中使用 std::weak_ptr::lock()
【发布时间】:2020-01-04 02:51:03
【问题描述】:

我有一个包含两个弱指针的结构,我希望使用 std::tie 按字典顺序比较这个结构。但是,我遇到了一个奇怪的问题,我意识到我不能使用 std::weak_ptr::lock() 作为 std::tie 的参数。 示例代码:

struct S {
    S(std::shared_ptr<int>& f, std::shared_ptr<int>& s) {
        first = f;
        second = s;
    }
    bool operator<(const S& rhs) const {
        return std::tie(first.lock(), second.lock()) < std::tie(rhs.first.lock(), rhs.second.lock());
    }
    std::weak_ptr<int> first, second;
};

这样做会导致编译错误,代码为E0304: no instance of function template "std::tie" matches the argument list

但是,如果我创建新的 std::shared_ptr 对象并将它们设置为 std::weak_ptr::lock() 的值,然后比较 它们,一切正常:

struct S {
    S(std::shared_ptr<int>& f, std::shared_ptr<int>& s) {
        first = f;
        second = s;
    }
    bool operator<(const S& rhs) const {

        // creating shared_ptrs and assigning them the value of std::weak_ptr::lock()

        std::shared_ptr<int> 
            f = first.lock(), s = second.lock(),
            rf = rhs.first.lock(), rs = rhs.second.lock();

        // compare those shared_ptrs
        return std::tie(f, s) < std::tie(rf, rs);
    }
    std::weak_ptr<int> first, second;
};

int main() {
    std::shared_ptr<int> 
        a(new int(10)),
        b(new int(5));

    // just two S initializations
    S foo(a, b);
    S bar(b, a);

    if (foo < bar) {
        std::cout << "Foo is less than Bar";
    }
    else {
        std::cout << "Otherwise";
    }

}

输出:Foo is less than Bar

这可能是什么原因?谢谢!

【问题讨论】:

  • 这样想。我可以锁定一个不属于我的对象吗(我有弱指针,它的引用计数不依赖于我)?如果在比较时,对象的引用计数降至零,会发生什么情况?
  • 这在 MSVC 2017 中编译得很好,但对我来说 gcc 9.2 失败了。
  • @FrançoisAndrieux 这是 MSVC 遗留的非标准规则的一个实例,允许将非常量引用绑定到右值。使用/permissive- 编译时,MSVC 也会拒绝它。
  • @aschepler 对,这就解释了。谢谢。

标签: c++


【解决方案1】:

std::tie 通过 reference 接收参数,因为它从它们构建了一个引用元组。临时对象,如lock() 返回的std::shared_ptr,不能绑定到引用。创建单独的变量为引用提供了绑定的东西。

【讨论】:

  • 我似乎错过了 std::tie 文档中的 '&',这很有意义。谢谢!
【解决方案2】:

std::tie 仅用于左值,创建返回类型,例如std::tuple&lt;T1&amp;, T2&amp;&gt;lock() 成员函数按值返回shared_ptr,因此表达式是右值,不能与std::tie 一起使用。

您可以通过写std::forward_as_tuple 来更普遍地使用相同的元组字典技巧:

return std::forward_as_tuple(first.lock(), second.lock()) < 
    std::forward_as_tuple(rhs.first.lock(), rhs.second.lock());

这些forward_as_tuple 调用的返回类型将是std::tuple&lt;std::shared_ptr&lt;int&gt;&amp;&amp;, std::shared_ptr&lt;int&gt;&amp;&amp;&gt;forward_as_tuple 通常比 tie 更危险一些,因为它在某些用途中可以创建没有编译器警告的悬空引用,但在这里它是安全的,因为 tuple 对象是临时的,不会在 operator&lt; 之后使用评估。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 2016-03-12
    • 2022-01-16
    • 2017-04-16
    • 2014-12-17
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    相关资源
    最近更新 更多