使用模板赋值运算符

rel*_*xxx 6 c++ templates

有下面的代码,为什么第一次分配不调用模板operator=Foo,但第二个呢?这里有什么?即使用户定义的模板存在,是否有编译器生成的第一个赋值?

#include <iostream>

using namespace std;

struct UberFoo { };

struct Foo : public UberFoo 
{
    template<typename T> void operator=(const T& v) { cout << "const T&" << endl; Set(v); }
    template<typename T> void operator=(T& v) { cout << "T&" << endl; return Set(v); }

    virtual void Set(const Foo&) { cout << "Foo::Set(const Foo&)" << endl; }
    virtual void Set(const UberFoo&) { cout << "Foo::Set(const UberFoo&)" << endl; }
};

struct Bar : public Foo 
{
    virtual void Set(const Foo&) { cout << "Bar::Set(const Foo&)" << endl; }
    virtual void Set(const UberFoo&) { cout << "Bar::Set(const UberFoo&)" << endl; }
};

int main()
{
    Bar a, b;

    Foo & pa = a;
    const Foo& rb = b;
    const UberFoo & urb = b;

    cout << "First" << endl;

    pa = rb;

    cout << endl << "Second" << endl;

    pa = urb;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

use*_*016 5

编译器仍然生成第一个赋值所绑定的非模板化 operator=.在第二个赋值中,模板化operator=是一个更好的候选者(因为它不涉及强制转换),因此选择一个.

您可以通过在代码中添加以下内容来查看:

Foo& operator=(const Foo&) = delete;
Run Code Online (Sandbox Code Playgroud)

或强制正确的模板调用:

pa.operator=<Foo>(b);
Run Code Online (Sandbox Code Playgroud)

标准说(强调我的):

12.8复制和移动类对象,§12.8/ 17,第271页:

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

§12.8/ 18,同页:

如果类定义未显式声明复制赋值运算符,则会式声明一个.