Это может никогда не сработать:
template<typename T>
my_class(typename std::enable_if<std::is_base_of<implementation, derived_1>::value, T&&>::type impl) : impl_(std::make_shared<T>(std::move(impl))) {}
template <typename T>
my_class& operator= (typename std::enable_if<std::is_rvalue_reference<T&&>::value && !std::is_same<T, my_class>::value, T&&>::type impl)
Причина в том, что вы используете T
только в не выведенных контекстах.Проще говоря, компилятор не может вывести T
, если аргумент, из которого он должен был вывести его, имеет форму Anything<T>::type
.
Итак, если вы хотите использовать enable_if
в операторе присваивания, вы помещаете еговозвращаемое значение:
template <class T>
typename enable_if<..., T&>::type operator=(const T&);
в случае конструктора преобразования (должен работать и для перемещения), вы добавляете фиктивный параметр со значением по умолчанию:
template <class T>
MyClass(const T&, typename enable_if<..., void>::type* =0);
FredOverflow уже дал вамправильный оператор присваивания.
Кстати, вам не нужно ограничивать его ссылками rvalue, если вы используете std::forward
вместо std::move
.Смотрите здесь .Это даст вам (скопируйте и вставьте из FredOverflow):
template <typename T>
typename std::enable_if<std::is_base_of<implementation, T>::value, my_class&>::type
operator=(T&& impl)
{
std::make_shared<implementation>(std::forward<T>(impl)).swap(impl_);
return *this;
}