pragMATHiC
pragMATHiC

Reputation: 408

Undefined reference to overloaded operator inside of namespace

I'm having trouble using an overloaded operator that's declared inside of a namespace.

The setup looks like this:

classa.h

#ifndef CLASSA_H
#define CLASSA_H

namespace ns1 {

class ClassA {
public:
  ClassA();

  enum class MyEnum : unsigned {
    VAL_A = 0,
    VAL_B = 1,
    VAL_C = 2,
    VAL_D = 4,
    VAL_E = 8
  };
};

// Declaration of overloaded operator
ClassA::MyEnum operator|(ClassA::MyEnum const &lhs, ClassA::MyEnum const &rhs);

} // namespace ns1

#endif // CLASSA_H

classa.cpp

#include "classa.h"

using ns1::ClassA;

ClassA::ClassA() {}

// Definition of overloaded operator
ClassA::MyEnum operator|(ClassA::MyEnum const &lhs, ClassA::MyEnum const &rhs) {
  return static_cast<ClassA::MyEnum>(static_cast<unsigned>(lhs) |
                                     static_cast<unsigned>(rhs));
};

and main.cpp

#include "classa.h"
#include <iostream>

using ns1::ClassA;

int main() {
  auto temp{ClassA::MyEnum::VAL_A | ClassA::MyEnum::VAL_B};
  std::cout << (unsigned)temp << std::endl;
  return 0;
}

The compiler produces:

error: undefined reference to `ns1::operator|(ns1::ClassA::MyEnum const&, ns1::ClassA::MyEnum const&)'

How can I use the definition of the overloaded operator in my program?

Upvotes: 0

Views: 254

Answers (2)

Swift - Friday Pie
Swift - Friday Pie

Reputation: 14589

using ns1::ClassA doesn't do what you expect. It only propagates ns1::ClassA id to global namespace but it doesn't affect definitions following it. operator| should be defined in ns1 scope.

namespace ns1 {
// Definition of overloaded operator
ClassA::MyEnum operator|(ClassA::MyEnum const &lhs, ClassA::MyEnum const &rhs) {
  return static_cast<ClassA::MyEnum>(static_cast<unsigned>(lhs) |
                                     static_cast<unsigned>(rhs));
};
}

Upvotes: 2

Thomas
Thomas

Reputation: 181725

You need to define the operator in the same namespace that it's declared in, otherwise you have two different, unrelated operators (one of which is undefined, and the other only defined in classa.cpp).

Just wrap the entire implementation in a namespace ns1 block:

classa.cpp

#include "classa.h"

namespace ns1 {

ClassA::ClassA() {}

// Definition of overloaded operator
ClassA::MyEnum operator|(ClassA::MyEnum const &lhs, ClassA::MyEnum const &rhs) {
  return static_cast<ClassA::MyEnum>(static_cast<unsigned>(lhs) |
                                     static_cast<unsigned>(rhs));
};

}

Upvotes: 4

Related Questions