2

The following code is a minimum code to reproduce my problem. When I try to compile it, the linker can not find operator== for Config:

Undefined symbols for architecture x86_64:
"operator==(Config<2> const&, Config<2> const&)", referenced from:
          _main in test2.o

The operator== is a friend of Config. BUT when I do no longer declare operator== as a friend, the code compilers with no error.

template <int DIM>
class Config{
    // comment the following line out and it works
    friend bool operator==(const Config<DIM>& a, const Config<DIM>& b);

    public:
        int val;
};

template <int DIM>
bool operator==(const Config<DIM>& a, const Config<DIM>& b){
    return a.val == b.val;
}

int main() {
    Config<2> a;
    Config<2> b;
    a == b;
    return 0;
}

What is the problem here?

Michael
  • 7,407
  • 8
  • 41
  • 84

1 Answers1

7

You have missed to declare the template in the friend declaration:

template <int DIM>
class Config{
    template <int DIM_> // <<<<
    friend bool operator==(const Config<DIM_>& a, const Config<DIM_>& b);

    public:
        int val;
};

If you want to have a friend function declaration you must use it's exact signature declaration. If this involves template parameters these must be specified independently from the enclosing template class or struct.


Here's a brilliant answer explaining the several aspects of friend declarations in depth.

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • Solves the problem but I have no clue WHY I have to define it as a template explicitly. – Michael May 03 '15 at 12:59
  • 1
    @Michael because otherwise you're not friending your template operator, you're friending (and declaring) just some specific operator == to friend with your *class* template. – WhozCraig May 03 '15 at 13:00
  • 1
    A friend function is just any ordinary function *outside* of the class that declares it as a friend. Now, just copy the friend declaration to outside the class, remove the `friend` and you will see it doesn't match the template function that you wrote. BTW, I wrote function because an operator is just a function with a special calling syntax. – Ulrich Eckhardt May 03 '15 at 13:01
  • So I have to tell the compiler: "Please look for a **template** and not a plain, non-template function." ? – Michael May 03 '15 at 13:01
  • @Michael Updated my answer a bit. – πάντα ῥεῖ May 03 '15 at 13:02
  • @Michael though not the same operator, the techniques for friending (and pitfalls you may not have considered) are well explained [in this answer to another question](https://stackoverflow.com/questions/4660123/overloading-friend-operator-for-template-class/4661372#4661372). – WhozCraig May 03 '15 at 13:03