Оператор присваивания шаблона не заменяет оператора присваивания по умолчанию

В шаблонах С++ Полное руководство в разделе 5.3. Шаблоны членов, которые он написал:

Обратите внимание, что оператор присваивания шаблона не заменяет значение по умолчанию оператор присваивания. Для присвоений стеков того же типа оператор присваивания по умолчанию все еще вызывается.

Это правильно, потому что, когда я бежал ниже кода:

#include<iostream>
using namespace std;

template<typename T>
class Pair
{
    public:
            T pair1,pair2;
            Pair(T i,T j):pair1(i),pair2(j){}
            template<typename T1>Pair<T>& operator=(Pair<T1>&);             
};

template<typename T>
template<typename T1>
Pair<T>& Pair<T>::operator=(Pair<T1>& temp)
{

    this->pair1 =temp.pair1*10;//At this point
    this->pair2=temp.pair2;
    return *this;
}

int main()
{

    Pair<int>P1(10,20);
    Pair<int>P2(1,2);
    P2=P1;
    cout<<P2.pair1<<' '<<P2.pair2<<endl;
    return 1;
}

Получил ответ 100 20.

Он не дал ответ назначения по умолчанию.

Является ли это типичной ошибкой в ​​шаблонах С++ для полного руководства?

С++ Templates: Полное руководство Дэвидом Вандевоордом, Николаем М. Йосутис

Издатель: Addison Wesley

Дата публикации: 12 ноября 2002 г. ISBN: 0-201-73484-2 Страницы: 552

Ответ 1

Оператор присваивания копий действительно неявно объявляется и рассматривается с помощью разрешения перегрузки.

Оператор копирования X::operator=, объявленный пользователем, является нестатическая функция без шаблона класса X [..].

Если определение класса не указано явно объявить оператор присваивания копии, один объявлен неявно. [..] Оператор присваивания неявным объявлением для класса X будет имеют вид

X& X::operator=(const X&)

если

  • каждый прямой базовый класс B of X имеет оператор присваивания копии, параметр которого имеет тип const B&, const volatile B& или B и
  • для всех нестатических членов данных X, которые относятся к типу класса M (или его массиву), каждый такой тип класса имеет назначение копирования оператор, параметр которого имеет тип const M&, const volatile M& или M.

В противном случае, [..]

Как вы видите, неявно объявленный оператор назначения копирования для Pair<int> имеет один параметр типа Pair<int> const& - обратите внимание на const в частности! Разрешение перегрузки поддерживает не const ссылки на const, если оба могут быть связаны с аргументом, [over.ics.rank]/3:

Две неявные последовательности преобразования одной и той же формы неразличимые последовательности преобразования, если одно из следующих применяются правила:

-  Стандартная последовательность преобразования S1 является лучшей последовательностью преобразования, чем стандартная последовательность преобразования S2 если

  • [..]
  • S1 и S2 являются привязками привязки (8.5.3) и типами, ссылки ссылаются на один и тот же тип, за исключением cv-квалификаторов верхнего уровня, и тип, на который ссылается ссылка, инициализированная на S2, больше cv-квалификатор, чем тип, к которому ссылка инициализируется S1относится.

Специализации шаблона не хватает const в эталонном параметре, поэтому он лучше сочетается и выбирается.

Ответ 2

Оператор присваивания по умолчанию принимает аргумент как ссылку на const: http://en.cppreference.com/w/cpp/language/as_operator.

Вы определили версию без const, и ваша версия лучше в контексте разрешения перегрузки (без необходимости преобразования).

Попробуйте следующее изменение:

int main()
{
    Pair<int>P1(10,20);
    Pair<int>P2(1,2);
    const Pair<int>& x = P1;
    P2=x;
    cout<<P2.pair1<<' '<<P2.pair2<<endl;
    return 1;
}

чтобы увидеть ожидаемый результат.