constrexpr 构造函数继承自 shared_ptr

constrexpr constructor inherited from shared_ptr

我想实现我自己的从 shared_ptr.

扩展而来的指针(使用一些辅助方法)
class Event;

class EventPtr : public std::shared_ptr<Event> {
public:
    constexpr EventPtr()
        : std::shared_ptr<Event>() {
    }

    constexpr EventPtr(std::nullptr_t p)
        : std::shared_ptr<Event>(p) {
    }

    explicit EventPtr(Event* ptr)
        : std::shared_ptr<Event>(ptr) {
    }
};

问题是编译器为我提供了以下两个 constexpr 构造函数的错误: constexpr 构造函数从不生成常量表达式

请告诉我如何解决它。

constexpr 构造函数的规则在 C++11 和 C++14 之间发生了变化;参见 DR1911 constexpr constructor with non-literal base class and this bug

修复是在 C++14 模式下编译 (-std=c++14)。

C++11 语言[dcl.constexpr]:

For a constexpr function, if no function argument values exist such that the function invocation substitution would produce a constant expression (5.19), the program is ill-formed; no diagnostic required. For a constexpr constructor, if no argument values exist such that after function invocation substitution, every constructor call and full-expression in the mem-initializers would be a constant expression (including conversions), the program is ill-formed; no diagnostic required.

在 C++11 下,shared_ptr 可以有 constexpr 构造函数,但是任何继承自 shared_ptr 或具有 shared_ptr 成员的 class 类型都不能,因为 shared_ptr 不是文字类型(它有析构函数)所以不能出现在常量表达式中。对于 C++14,这被简化为:

For a non-template, non-defaulted constexpr function or a non-template, non-defaulted, non-inheriting constexpr constructor, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.19), the program is ill-formed; no diagnostic required.

不幸的是,这使得 all constexpr 非文字类型的构造函数未定义行为; DR1911 通过添加子条款(下面的 粗体 )解决了这个问题:

For a non-template, non-defaulted constexpr function or a non-template, non-defaulted, non-inheriting constexpr constructor, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.20), or, for a constructor, a constant initializer for some object (3.6.2), the program is ill-formed; no diagnostic required.

struct X { ~X() {} constexpr X() {} };   // OK in C++11, UB in C++14, OK since DR1911
struct Y : X { constexpr Y() : X() {} }; // UB in C++11, UB in C++14, OK since DR1911