I want to implement my own pointer (with few helper methods) extended from 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) {
}
};
The problem is that compiler gives me the following error for both constexpr constructors: constexpr constructor never produces constant expression
Tell me please how to fix it.
The rules on constexpr constructors changed between C++11 and C++14; see DR1911 constexpr constructor with non-literal base class and this bug.
The fix is to compile in C++14 mode (-std=c++14
).
Language in 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.
Under C++11, shared_ptr
can have constexpr
constructors but any class type inheriting from shared_ptr
or with a shared_ptr
member cannot, because shared_ptr
is not a literal type (it has a destructor) and so cannot appear in a constant expression. For C++14 this was simplified to:
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.
Unfortunately this makes all constexpr constructors of non-literal types undefined behavior; DR1911 fixed this by adding a subclause (bolded below):
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