I'm creating an implementation of C++17's std::optional<class T>
in C++14. The specification states that the move constructor should be excluded from overload resolution if T
is not move-constructible, and made trivial if T
is trivially move-constructible. I'm stuck on getting the former.
Here's a code sample of what I have so far:
template<class T, bool = is_trivially_move_constructible_v<T>>
class optional_move_construct : public optional_copy_construct<T> {
public:
optional_move_construct(optional_move_construct&& rhs) :
optional_base<T>() {
if (rhs.m_full) {
_impl_construct(std::move(rhs.m_value));
}
}
};
optional_copy_construct<T>
is part of the inheritance chain I'm using, so I won't worry about it.
There are two ways I can "remove" the move constructor, neither of which works for this scenario.
Option 1: Delete the move constructor. This won't work because deleted functions are included in overload resolution.
Option 2: Use SFINAE to exclude the move constructor from overload resolution. This won't work either, because SFINAE requires a template function to work, and that would be lower-priority than the default move constructor.
How would I go about doing this?
A move constructor has one T&&
argument, and possibly additional arguments provided those have default values. That means you can add std::enable_if_t<Condition, int> = 0
as an additional argument to your move constructor.
The compiler won't create a one-argument optional::optional(T&&)
move constructor when you have that two-argument move constructor.