Reputation: 3142
I want to redefine unique_ptr
with a special destructor. Therefore I use the following code where I try to mimic some constructors of unique_ptr
. Unfortunately constexpr
constructors refuse to build and I have no idea why.
class job_ptr : public unique_ptr<Job>
{
public:
constexpr job_ptr()
: unique_ptr<Job>(), sequencer( nullptr ) {}
constexpr job_ptr( nullptr_t )
: unique_ptr<Job>( nullptr ), sequencer( nullptr ) {}
private:
FIFOSequencer* sequencer;
};
Both constructors in the initialisation list are declared constexpr
, however clang++
considers that constexpr constructor never produces a constant expression
because non-literal type 'unique_ptr<Job>' cannot be used in a constant expression
. What does it try to mean ? constexpr
constructors cannot be used within constexpr
constructors ?
Thank you for any help.
Upvotes: 0
Views: 3916
Reputation: 3778
Constexpr constructors are possibles, but the requirement are quite strict. The main problem for you is, as @dyp said, that std::unique_ptr
as no trivial destructor and thus is not a LiteralType
.
If you try with an int
under g++:
class int_ptr : public std::unique_ptr<int>
{
public:
constexpr int_ptr()
: std::unique_ptr<int>(), sequencer( nullptr ) {}
constexpr int_ptr( nullptr_t )
: std::unique_ptr<int>( nullptr ), sequencer( nullptr ) {}
private:
int* sequencer;
};
constexpr int_ptr ptr;
You have a very explicit error message :
unique_ptr.cpp:40:20: error: the type ‘const int_ptr’ of constexpr variable ‘ptr’ is not literal
constexpr int_ptr ptr;
^
unique_ptr.cpp:27:7: note: ‘int_ptr’ is not literal because:
class int_ptr : public std::unique_ptr<int>
^
unique_ptr.cpp:27:7: note: ‘int_ptr’ has a non-trivial destructor
In your case, as suggested in the comment, use a custom deleter. STL container are not really well suited for inheritance.
Here an example of a custom deleter:
#include <memory>
#include <iostream>
template <typename T>
struct Deleter
{
void operator()(T* t)
{
std::cout << "Deleter::oerator(): " << t << std::endl;
delete t;
}
};
struct A
{
A()
{
std::cout << "A::A()" << std::endl;
}
~A()
{
std::cout << "A::~A()" << std::endl;
}
};
int main(int argc, char const *argv[])
{
std::unique_ptr<A, Deleter<A>> ptr(new A);
return 0;
}
It outputs:
A::A()
Deleter::oerator(): 0x600010480
A::~A()
Upvotes: 5