I'm trying to pack a (STL-)container of non-copyable type into an std::optional, e. g.:
class MyClass
{
MyClass(const MyClass&) = delete;
};
std::optional<std::list<MyClass>> optContainer;
But the compiler (GCC 7.2) complains
error: use of deleted function 'MyClass::MyClass(const MyClass&)' { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
[...] note: declared here
MyClass(const MyClass&) = delete;
and presents a deep "required from ..." stack going into type_traits (and more) where it checks for std::is_trivially_copy_constructible on the std::list. I suspect that there the compiler finds the container (std::list in the example) to be trivially copy constructible but does not check the value type of the container for trivial constructability and then goes the wrong path.
Of course the non-copyable type (not in a container) in an std::optional works:
std::optional<MyClass> optValue; // ok
I know that I can work around that e. g. like so:
template<typename T>
class CNonCopyable : public T
{
public:
template<typename... Params>
CNonCopyable(Params&&... params)
: T(std::forward<Params>(params)...)
{}
CNonCopyable(const CNonCopyable&) = delete;
CNonCopyable(CNonCopyable&&) = default;
virtual ~CNonCopyable() = default;
CNonCopyable& operator=(const CNonCopyable&) = default;
CNonCopyable& operator=(CNonCopyable&&) = default;
};
std::optional<CNonCopyable<std::list<MyClass>>> optContainer;
But I wonder if there is a better way without the CNonCopyable class.
(Just as an example where no own type is involved:) Same occurs when trying to pack a container of std::unique_ptr into an std::optional, because std::unique_ptr is not copy constructible:
std::optional<std::list<std::unique_ptr<int>>> optContainer;
This was a bug in GCC that has since been patched.
See 81190 and 80654
Use a newer version of GCC (e.g., 8) and you will not encounter the issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With