我有一个带有用于隐式移动转换的模板化构造函数的类,但是这个构造函数不应该用于该类(它应该只是可复制构造的)。但是,编译器总是尝试使用模板化的构造函数,而不是常规的复制构造函数。
例如,我得到了下面的编译器错误,link。(如果你想试一下,你可以直接复制粘贴这段代码)
struct implementation{};
class my_class
{
my_class(my_class&&); // delete move-constructor... OUCH... COMPILER ERROR
public:
my_class(){}
my_class(const my_class& other) : impl_(other.impl_){}
template<typename T>
my_class(T&& impl) : impl_(std::make_shared<T>(std::move(impl))){} // Still tries to use this...
private:
std::shared_ptr<implementation> impl_;
};
class other_class
{
public:
my_class foo()
{
return instance_; // Wants to use move-constructor???
}
private:
my_class instance_;
};有人知道如何正确解决这个问题吗?
发布于 2010-12-12 06:49:33
好的,这是我对my_class的彻底改造
class my_class
{
public:
my_class() {}
my_class(my_class&& that) : impl_(std::move(that.impl_)) {}
template <typename T> my_class(T&& impl,
typename std::enable_if<
std::is_base_of<
implementation,
typename std::remove_reference<T>::type
>::value,
void
>::type* dummy = 0
) : impl_(std::make_shared<T>(std::forward<T>(impl))) {}
template <typename T>
typename std::enable_if<
std::is_base_of<
implementation,
typename std::remove_reference<T>::type
>::value,
my_class&
>::type
operator=(T&& impl)
{
std::make_shared<implementation>(std::forward<T>(impl)).swap(impl_);
return *this;
}
private:
std::shared_ptr<implementation> impl_;
};正如其他人所建议的,通过使用std::forward而不是std::move,这适用于左值和右值引用。remove_reference是必需的,因为对于左值引用,T是引用,derived&不是从base派生的,但derived派生(注意引用)。
发布于 2010-12-12 09:12:11
这永远不会起作用:
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。简单地说,如果编译器应该从中推导出的参数的形式是Anything<T>::type,那么它就不能推导出T。
所以,如果你想在赋值运算符上使用enable_if,你可以把它放在返回值中:
template <class T>
typename enable_if<..., T&>::type operator=(const T&);在转换(也应该适用于move )构造函数的情况下,添加一个带有默认值的伪参数:
template <class T>
MyClass(const T&, typename enable_if<..., void>::type* =0);FredOverflow已经为您提供了正确的赋值运算符。
顺便说一句,如果您使用std::forward而不是std::move,则不必将其限制为右值引用。参见here。这将为您提供(从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;
}https://stackoverflow.com/questions/4419375
复制相似问题