构建一个constexpr std::weak_ptr

4
根据 std::weak_ptr 文档,可以构造一个 constexprweak_ptr:
#include <memory>
constexpr weak_ptr<int> foo{};

然而,使用clang尝试编译时会产生一个编译错误,抱怨constexpr变量不能具有非字面类型“const std::weak_ptr<int>”,这是因为weak_ptr<int>有一个用户提供的析构函数(通过查看libc ++头文件可以看到)。
我的问题是,这是libc++的一个bug,还是constexpr weak_ptr毫无意义,拥有constexpr默认构造函数是一个错误? 我可以期望将来能够正常工作吗?

weak_ptr 的析构函数负责释放 shared_ptr 控制块(也就是 weak_ptr 所依附的对象),因此我认为它不能是 constexpr - Cheers and hth. - Alf
请链接或引用您所参考的文档。 - Cheers and hth. - Alf
我在C++14中看到(最终草案N3290)默认构造函数是“constexpr”。这让我感到困惑。 - Cheers and hth. - Alf
这里是en.cppreference的参考链接:http://en.cppreference.com/w/cpp/memory/weak_ptr/weak_ptr。C++11标准在§20.7.2.3.1中列出了`constexpr weak_ptr() noexcept;`。 - md5i
2
DR827中有一些有趣的讨论。 - md5i
1个回答

8

这是libc++的一个bug吗?

不是。

constexprweak_ptr是没有意义的吗?

是的。

在非字面类型上使用constexpr默认构造函数是一个错误吗?

不是。在非字面类型上使用constexpr构造函数允许静态和线程存储期变量进行常量初始化,这发生在任何动态初始化之前。

这意味着,例如全局默认构造的weak_ptr对象总是被初始化,并且可以安全地用于全局对象的构造函数中。

// TU 1
namespace foo {
   std::weak_ptr<int> meow;
}

// TU 2
namespace foo {
   extern std::weak_ptr<int> meow;
}

struct C {
    C() { /* can safely use foo::meow here */ }
} c;

我能期待这个 [constexpr weak_ptr] 在未来工作吗?

不行。


我没有看到关于它的缺陷报告。您知道默认构造函数上constexpr的基本原理吗? - Cheers and hth. - Alf
1
@Cheersandhth.-Alf 就像我说的,它允许常量初始化。 - T.C.
@Cheersandhth.-Alf:我认为这样做可以更容易地避免像T.C.示例中的静态初始化惨案。否则,您将不得不使用一些复杂的单例构造或返回原始指针。 - Chris Beck
@ChrisBeck:是的,但接下来会有一个维护程序员发现跨TU引用,并且不知道这个额外的角落情况,花费一些时间(我们说本地构建和单元测试需要45分钟)重新实现为一个安全的单例模式。胜利=失败。 - Cheers and hth. - Alf
2
这是那种“哇,我今天学到了东西”的答案之一。 - Richard Hodges
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接