【发布时间】:2015-03-07 05:23:44
【问题描述】:
我正在使用编译器上的移动语义,它具有右值引用但不支持默认的移动构造函数。我想生成类似于下面的包装类的东西,即使模板参数是左值引用,它也可以工作。但是,这种简单的方法无法编译,因为它尝试从 int 初始化 int&。
#define USER_DEFINED 0
template <typename T>
struct Wrapper
{
Wrapper(T t)
: m_t(t)
{
}
Wrapper(const Wrapper&) = delete;
Wrapper& operator=(const Wrapper&) = delete;
#if USER_DEFINED
Wrapper(Wrapper&& w)
: m_t(std::move(w.m_t))
{
}
#else
Wrapper(Wrapper&&) = default;
#endif
private:
T m_t;
};
int main()
{
int i = 0;
Wrapper<int&> w1 = Wrapper<int&>(i);
Wrapper<std::string> w2 = Wrapper<std::string>("text");
}
显而易见的解决方案是使用两个移动构造函数,一个用于左值引用,一个用于所有其他类型。例如这样的事情:
template <typename U = T>
Wrapper(typename std::enable_if<!std::is_lvalue_reference<U>::value, Wrapper>::type&& w)
: m_t(std::move(w.m_t))
{
}
template <typename U = T>
Wrapper(typename std::enable_if<std::is_lvalue_reference<U>::value, Wrapper>::type&& w)
: m_t(w.m_t)
{
}
所以这是要走的路吗?也许enable_if<> 中的表达式应该更通用?或者我可以使用与 std::move() 不同的东西并为所有类型使用一个构造函数吗?
【问题讨论】:
-
我很犹豫是否将其发布为答案,因为我不确定它是否会做正确的事情,但是将
std::move替换为std::forward怎么样? -
@5gon12eder:去吧。你在正确的轨道上。
-
@HowardHinnant 谢谢。我试了一下,它似乎有效,但如果您有时间,我会很高兴收到一些反馈,因为我不完全理解它为什么真的有效。
标签: c++ c++11 move-semantics