5

在下面的代码中,使用的好处是&&什么?该代码来自针对不同特征的 Specialize same operator 的回答

这个问题,我得到一个&&参数意味着它是一个可以被函数修改的引用。

可能会阻止编译器将对变量的decay_t引用解释为数组,如什么是 std::decay 以及何时应该使用它?

std::forward是这里描述的完美转发。为什么我们需要这个转发?

谢谢。

#include <iostream>
#include <type_traits>
#include<utility>

class A;

template <typename T>
struct is_A : std::false_type {};
template <> struct is_A<A> : std::true_type {};

template <typename T>
struct is_int : std::false_type {};
template <> struct is_int<int> : std::true_type {};
template <> struct is_int<long> : std::true_type {};

class A{
public:
    int val;

    void print(void){
        std::cout << val << std::endl;
    }

    template <typename T1>
    std::enable_if_t<is_int<std::decay_t<T1>>::value, void>
    operator=(T1 && input){
        val = 2*std::forward<T1>(input);
    }

    template <typename T1>
    std::enable_if_t<is_A<std::decay_t<T1>>::value,void>
    operator=(T1 && Bb){
        val = 5*std::forward<T1>(Bb).val;
    }
};

int main(void){
    A Aa;
    A Bb;
    int in_a = 3;
    Aa = in_a;
    Bb = Aa;
    Aa.print(); //This should give 6. (3x2)
    Bb.print(); //This should give 30. (6x5)
}
4

1 回答 1

3

实际上,这是一个(让我说)技巧,因此示例代码有效。
事实上,标准说:

用户声明的复制赋值运算符 X::operator= 是类 X 的非静态非模板成员函数,只有一个 X、X&、const X&、volatile X& 或 const volatileX& 类型的参数。

而且:

如果类定义没有显式声明复制赋值运算符,则隐式声明一个。 

现在,尝试复制分配对变量的 const 引用,例如:

Bb = static_cast<const A&>(Aa);

结果将不再是预期的结果。

无论如何,只要您只处理非 cv 限定的左值/右值引用,答案中使用的转发引用就可以正常工作,如示例代码所示。
拦截了一堆特定的类型并完成它的工作。就这样。

正如@Jarod42 的评论中提到的:

请注意,您仍然必须编写operator=(const A&)来处理它,因为它很特殊。

确实没那么特别。如果您没有定义它,则该代码中没有正确的复制赋值运算符。
正如评论中所说,定义它

[...] 留给读者作为练习。:-)

那么,这样做有什么好处呢?
提供最小的、有效的解决方案的捷径。当然,这不是一个完整的、可用于生产的代码。

于 2016-09-16T17:56:33.757 回答