2

I am trying to overload the operator= in a template class.

I have this template class:

template <class T>
class Matrice
{
    T m,n;
public:
    template <class V>
    friend Matrice<V>& operator=(const Matrice<V> &);
};

template <class T>
Matrice<T>& Matrice<T>::operator=(const Matrice<T> &M)
{
    /*...*/
    return *this;
}

and I also tried:

template <class T>
class Matrice
{
    T m,n;
public:
    template <class V>
    Matrice<V>& operator=(Matrice<V> &);
};

template <class T>
Matrice<T>& operator=(Matrice<T> &M)
{
    /*...*/
    return *this;
}

but I still get this error:

error C2801: 'operator =' must be a non-static member
Griwes
  • 8,805
  • 2
  • 43
  • 70
Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113

3 Answers3

5

error C2801: 'operator =' must be a non-static member

The bolded word is key here. friend is not a member; it's a friend. Remove that friend keyword and treat operator= as member:

The syntactically proper version is:

template <class T>
class Matrice
{
    T m,n;
public:
    template <class V>
    Matrice<V>& operator=(const Matrice<V> &);
};

template <class T>
template <class V>
Matrice<V>& Matrice<T>::operator=(const Matrice<V> &M)
{
    /*...*/
    return *this;
}

Although I think that it's wrong to use that template <class V> there; the sematically proper version would be

template <class T>
class Matrice
{
    T m,n;
public:
    Matrice<T>& operator=(const Matrice<T> &);
};

template <class T>
Matrice<T>& Matrice<T>::operator=(const Matrice<T> &M)
{
    /*...*/
    return *this;
}

Explanation: you don't generally want to assign Type<V> to Type<T> in this way; if you have to, then it is probably sign of bad design.

Griwes
  • 8,805
  • 2
  • 43
  • 70
  • With your example i get this error message: `error C2244: 'Matrice::operator =' : unable to match function definition to an existing declaration` – Iulian Onofrei Jun 23 '12 at 19:45
  • @RevoltEr, nah, just noticed it. Let me fix it. – Griwes Jun 23 '12 at 19:46
  • Bojan Komazec's solution looks simpler; should I use his or yours? Or both do the same thing? – Iulian Onofrei Jun 23 '12 at 19:55
  • @RevoltEr, Bojan's answer is same as my second snippet, that eliminates second template parameter, that doesn't really make sense when used in the original way. – Griwes Jun 23 '12 at 19:56
  • In your second snippet you have `Matrice &` instead of `Matrice &` – Iulian Onofrei Jun 23 '12 at 19:59
  • @RevoltEr, ups, sorry, typo that was. Fixed now. – Griwes Jun 23 '12 at 20:00
  • Explain to me how you return a `Matrice` from a `Matrice` by saying `return *this;` – Fozi Jun 23 '12 at 20:03
  • @Fozi, in case you didn't notice - I said that it's syntactically correct version, and that's true, given code from OP, as we cannot assume anything else - http://ideone.com/icA8C. And above second snippet I said that *the second snippet* is **semantically** correct, which is also true. So, where is your problem now? – Griwes Jun 23 '12 at 20:06
  • @Fozi, as code from original post obviously isn't full code, how safe is it to assume that there is no `template operator Matrice()` somewhere? – Griwes Jun 23 '12 at 20:11
  • For one, because you return a reference. The second reason is that if you create a copy you would not actually change the state of the object you are trying to assign to. But yes, theoretically you could have a valid implementation that compiles an maybe even does something sensible. – Fozi Jun 23 '12 at 20:14
  • @Fozi, good point about the reference; anyway, the code in given form can be compiled, that's why I wrote that it's **syntactically** correct. – Griwes Jun 23 '12 at 20:15
3

The standard says

12.8 Copying and moving class objects [class.copy]

...

17 A user-declared copy assignment operator X::operator= is a non-static non-template member function of class X with exactly one parameter of type X, X&, const X&, volatile X& or const volatile X&.

A friend function doesn't fulfill these requirements. It must be a member function.


To address the comments that this is just "plain" assignment, not copy assignment, let's add another quote from the standard:

13.5.3 Assignment [over.ass]

An assignment operator shall be implemented by a non-static member function with exactly one parameter.

In standardese, "shall" doesn't leave any options to do anything else.

Community
  • 1
  • 1
Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • An operator = must not necessarily be the copy assignment operator. – Fozi Jun 23 '12 at 19:55
  • @Fozi, in what case `X::operator=()` isn't the copy assignment operator? Note: OP want `X::operator=()`, not `X a = X();`... – Griwes Jun 23 '12 at 19:57
  • 1
    Just because it's overloading the = operator does not mean that it's copying. Pretty much any overload of the = operator that does not follow your rules above is not a copy assignment operator and will allow the compiler to create a generated one. – Fozi Jun 23 '12 at 20:01
2

You mixed friend and member declarations and definitions: in the first example you declared operator= as a friend but defined it as a class member. In the second example, you declared operator= as a member but tried to define it as a non-member. Your operator= has to be a member (see this question why) and you can do the following:

template <class T>
class Matrice
{
    T m,n;
public:
    Matrice<T>& operator=(Matrice<T> &);
};

template <class T>
Matrice<T>& Matrice<T>::operator=(Matrice<T> &M)
{
    /*...*/
    return *this;
}
Community
  • 1
  • 1
Bojan Komazec
  • 9,216
  • 2
  • 41
  • 51