复制构造函数作为模板化成员函数被忽略

时间:2015-10-27 19:33:56

标签: c++ templates

是否可以将赋值运算符推导为成员函数模板的特例?

例如,我有一个带有一个bool参数的类模板,并且想要实现assign操作,而不管模板参数的任何特定值。

#include <iostream>

template<bool sw>
struct A {
    A() {
        std::cout << __PRETTY_FUNCTION__ << '\n';
    }

    template<bool input_sw>
    A & operator = (const A<input_sw> &a) {
        std::cout << __PRETTY_FUNCTION__ << '\n';
        return *this;
    }
};

int main()
{
    A<true> a;
    A<true> b;
    a = b;
}

在上面的代码片段中,clang和gcc编译的二进制文件不打印任何关于赋值的内容 - 据我所知,默认赋值在这里生成,尽管可以从模板中推断出它。

1 个答案:

答案 0 :(得分:6)

他们不打印任何东西是正确的。发生的事情是,为A<true>创建了一个带有此签名的隐式复制赋值运算符:

A<true>& operator=(const A<true>& );

因此,当我们进行重载决策时,有两个可行的候选者:

A<true>& operator=(const A<true>& );     // implicit copy assignment
A<true>& operator=(const A<input_sw>& ); // [ with input_sw = true ]

两个运算符都采用相同的参数(const A<true>&),因此从这个角度看它们是等同的好候选者。但非模板函数比函数模板特化更受欢迎,这使得隐式复制赋值运算符成为最佳可行候选者。

现在,考虑另一种选择。如果您以这种方式声明操作员模板,该怎么办:

template<bool input_sw>
A & operator =(A<input_sw> &a) { ... }

即,不是const。这不是一种好的做法,我只是为了说明目的而提出这一做法。在这种情况下,a=b的两位候选人是:

A<true>& operator=(const A<true>& );   // implicit copy assignment
A<true>& operator=(A<input_sw>& );     // [ with input_sw = true ]

现在两个候选人采取相同的论点。我们的运算符模板引用了非const。在两个引用的情况下,引用最后一个 cv - 限定类型的引用是优选的,在这种情况下它将是运算符。删除const,现在您的功能是首选,您将看到打印的内容。

C ++是最好的。