请考虑以下代码:
class Test
{
public:
Test()
{
}
Test(const Test &other) noexcept
{
*this = other;
}
Test(Test &&other) noexcept
{
*this = std::move(other);
}
auto operator = (const Test &other) noexcept -> Test&
{
// Make a copy of "other"
// ...
return *this;
}
auto operator = (Test &&other) noexcept -> Test&
{
// Move "other"
// ...
return *this;
}
};
我想组合移动和复制构造函数。根据我的理解,可以使用std :: forward来实现:
template <class T>
Test(T &&other) noexcept
{
*this = std::forward<T>(other);
}
如果仔细使用,它看起来效果很好:
Test test;
Test test1 { test };
Test test2 { std::move(test) };
另一方面,如果我尝试实例化一个类型不同于Test的Test对象,它会创建一个无限递归:
Test test { 1 }; // Creates an infinite recursion
有没有办法用Test类型的(r || l)值限制Test对象的实例化?
答案 0 :(得分:4)
无限递归是由在赋值操作中构造的Test
实例引起的,它涉及再次调用构造函数。原因是您没有为Test
以外的任何内容定义赋值运算符。
更准确地说,请阅读:
template<typename T>
Test(T &&other)
{
*this = forward<T>(other);
}
这样:
template<typename T>
Test(T &&other)
{
this->operator = (Test{forward<T>(other)}); // <- Recursion here
}
适用于T
以外的任何Test
。
要解决此问题,您需要定义一个适当约束的赋值运算符,如下所示:
template<typename T>
auto operator = (T &&value)
-> typename std::enable_if<
! std::is_same<typename std::decay<T>::type, Test>::value,
Test &
>::type
{
// Assignment involving a T that is not a Test
return *this;
}