Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

container of non-copyable in std::optional

Tags:

c++

c++17

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;
like image 475
Lorenz Zhao Avatar asked Feb 26 '18 15:02

Lorenz Zhao


1 Answers

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.

like image 146
AndyG Avatar answered Oct 22 '22 01:10

AndyG