std :: forward无限递归大小效果

时间:2015-07-19 16:20:09

标签: c++ c++11

请考虑以下代码:

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对象的实例化?

1 个答案:

答案 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;
}