简体   繁体   中英

Template assignment operator doesn't replace the default assignment operator

In C++ Templates The Complete Guide in section 5.3 Member Templates it's written:

Note that a template assignment operator doesn't replace the default assignment operator. For assignments of stacks of the same type, the default assignment operator is still called.

Is this correct, because when I ran below code:

#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;
}

I got answer 100 20.

It didn't give the default assignment answer.

Is that a typing mistake in C++ Templates the Complete Guide ?

C++ Templates: The Complete Guide By David Vandevoorde, Nicolai M. Josuttis

Publisher : Addison Wesley

Pub Date : November 12, 2002 ISBN : 0-201-73484-2 Pages : 552

The copy assignment operator is indeed implicitly declared and considered by overload resolution.

A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X [..].

If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly . [..] The implicitly-declared copy assignment operator for a class X will have the form

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

if

  • each direct base class B of X has a copy assignment operator whose parameter is of type const B& , const volatile B& or B , and
  • for all the non-static data members of X that are of a class type M (or array thereof), each such class type has a copy assignment operator whose parameter is of type const M& , const volatile M& or M .

Otherwise, [..]

As you can see the implicitly-declared copy assignment operator for Pair<int> has one parameter of type Pair<int> const& - note the const in particular! Overload resolution favours non- const references over const ones if both can be bound to the argument, [over.ics.rank]/3:

Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of the following rules applies:

— Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if

  • [..]
  • S1 and S2 are reference bindings (8.5.3), and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers.

The specialization of the template lacks a const in the reference parameter, thus it's a better match and is selected.

The default assignment operator accepts the argument as a const reference: http://en.cppreference.com/w/cpp/language/as_operator .

You have defined a version without const , and your version is better in the context of overload resolution (no conversion required).

Try with the following change :

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

to see the expected result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM