What does "operator = must be a non-static member" mean?

77,500

Solution 1

Exactly what it says: operator overloads must be member functions. (declared inside the class)

template<class T>
void list<T>::operator=(const list<T>& rhs)
{
    ...
}

Also, it's probably a good idea to return the LHS from = so you can chain it (like a = b = c) - so make it list<T>& list<T>::operator=....

Solution 2

Put that operator inside your class definition. It must be a member because operator= is special and you would not gain something by writing it as a non-member anyway. A non-member operator has two important main benefits:

  • Implicit conversions of the right and the left side of the operator invocation
  • No need to know about internals of the class. Function can be realized as non-member non-friend.

For operator=, both is not usable. Assigning to a temporary result of a conversion does not make sense, and operator= will need access to internals in most cases. In addition, a special operator= is automatically provided by C++ if you don't provide one (the so-called copy-assignment operator). Making it possible to overload operator= as a non-member would have introduced additional complexity for apparently no practical gain, and so that isn't allowed.

So change your code so that it looks like this (this assumes the operator= is not a copy-assignment operator, but assigning from a list<T> to something else. This isn't clear from your question):

class MyClass {
...
    template<class T>
    MyClass& operator=(const list<T>& lst)
    {
        clear();
        copy(lst);
        return *this;
    }
...
};

It's pretty standard that a operator= returns a reference to itself again. I recommend you to adhere to that practice. It will look familiar to programmers and could cause surprises if it would return void all of a sudden.

Solution 3

If you overload an operator as a member function, you should use this template:

class A {
  A& operator=(const A& other) {
    if (this != &other) {
      ...
    }
    return *this;
  }
}

Three things to note:

  1. Check for self-assignment with the assignment operator (as above);
  2. The argument should be a const reference; and
  3. Return the result of the operation as a non-const reference where you return *this to allow chaining of operators.

You can also overload an operator external to the class. This isn't relevant to this example because you can't do it with the assignment operator but it's worth noting because in many cases it's superior to member functions. The typical form is:

class A {
  friend const A& operator+(const A& a, const A& b);
  ...
}
const A& operator+(const A& a, const A& b) {
  A& ret = ...
  return ret;
}

This one returns a const reference so you can't do this:

(a + b) = c
Share:
77,500

Related videos on Youtube

Cam
Author by

Cam

Software engineer

Updated on July 09, 2022

Comments

  • Cam
    Cam almost 2 years

    I'm in the process of creating a double-linked list, and have overloaded the operator= to make on list equal another:

    template<class T>
    void operator=(const list<T>& lst)
    {
        clear();
        copy(lst);
        return;
    }
    

    but I get this error when I try to compile:

    container_def.h(74) : error C2801: 'operator =' must be a non-static member
    

    Also, if it helps, line 74 is the last line of the definition, with the "}".

    • bdonlan
      bdonlan almost 15 years
      What context is this in? In the class? At toplevel?
    • Simon Hartcher
      Simon Hartcher almost 15 years
      Don't really need the language in the question name since its also tagged C++
    • anton_rh
      anton_rh about 8 years
      This question is misleading. The question here is more interesting. Though the best wording would be "Why can't operator= be global". The answer by Johannes Schaub - litb clarifies that.
  • v3.
    v3. almost 15 years
    Does it really have to be static? No static works fine for me in g++.
  • Admin
    Admin almost 15 years
    Yeah, I just realized: I declared it in the class, but wrote "void operator=" instead of "void list<T>::operator="
  • Lordn__n
    Lordn__n almost 15 years
    Sorry getting my wires crossed. Functions not within classes are static by default. You can put the static keyword in but it's not necessary so there's no difference so I removed it.
  • Johannes Schaub - litb
    Johannes Schaub - litb almost 15 years
    the operator= must be a member (same is true for operator[]). I would use another example to show the non-member way.
  • Johannes Schaub - litb
    Johannes Schaub - litb almost 15 years
    I'm sorry, but this is wrong. operator= must be a member (like the compiler says). Same is true for operator[] and operator() and possibly some others i miss. Basically all those that have to do with modifying state instead of producing a value. Correct your answer and i'll retract the -1. Keand64's problem was he missed to specify the class (list<T>::), which hasn't got much to do with this answer.
  • v3.
    v3. almost 15 years
    Oh, oops. Sorry about that ><
  • Markus Mayr
    Markus Mayr almost 11 years
    Your answer is still misleading. It is not about the fact that operator overloads with 1 parameter must be member functions, but that there is no two parameter version of the assignment operator.
  • mpb
    mpb almost 10 years
    The original question was about operator =, which is not (per the C++ standard) a "Binary Operator". You cited paragraph 13.5.2.1. However, assignment operators are discussed in section 13.5.3: "An assignment operator shall be implemented by a non-static member function with exactly one parameter. ..."
  • juanchopanza
    juanchopanza about 8 years
    "operator overloads with 1 parameter must be member functions." Not true. You've been told this back in 2009. Maybe it is time to fix this answer.