https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70472
--- Comment #3 from Askar Safin <safinaskar at mail dot ru> --- (In reply to Jonathan Wakely from comment #2) > It's not required, and it would be impossible to require it in general. The > problem is that std::vector does have a copy constructor, so the trait value > is true, but instantiating that constructor produces an error when the > value_type is not copyable. std::is_copy_constructible<std::experimental::optional<...>> is correct. Look at the implementation. There are _Enable_special_members and _Enable_copy_move in <bits/enable_special_members.h>. Then there is _Optional_base in <experimental/optional>. And then there is template<typename _Tp> class optional : private _Optional_base<_Tp>, private _Enable_copy_move< // Copy constructor. is_copy_constructible<_Tp>::value, ... > in <experimental/optional>. Also, link I post ( http://paste.debian.net/422907/ ) give simplified example how to do this. > Types used with std::vector must be nothrow-move-constructible or > copy-constructible. If your type has a throwing move-ctor then vector will > try to copy it, which causes an instantiation error. If I remove copy-ctor and copy-assignment using "= delete" in that paste.debian.org link and leave noexcept commented, then all will build successfully. So, it seems for me vector uses the following algorithm: if (has_noexcept_move_ctor) { use_noexcept_move_ctor (); } else if (has_copy_ctor) // determined using trait. So if copy ctor is defined, it will be used, even if it doesn't compile. If copy ctor is deleted using "= delete", it will not be used { use_copy_ctor (); } else { use_move_ctor (); }