Search code examples
c++templatesfunction-pointerslinker-errorsfriend

How do i get a function pointer to a friend function defined inside a template class


I want to define a template class Foo<T> and a template function func<T>, so that func<T> is a friend of Foo<T>, but func<T1> is NOT a friend of Foo<T2> for T1 != T2. As far as I know, there are two ways to do this.

1:

template < typename T >
class Foo;

template < typename T >
void func(Foo<T> x);

template < typename T >
class Foo {
    friend void func<>(Foo<T>);
};

template < typename T >
void func(Foo<T> x) {}

2:

template < typename T >
class Foo;

template < typename T >
void func(Foo<T> x);

template < typename T >
class Foo {
    friend void func(Foo) {}
};

In both cases I can call func like this

int main(void) {
    Foo<int> a;
    func(a);

But when I try to get a function pointer

    (&func)(a);
}

the second version fails with a linker error:

/tmp/ccOICrUD.o: In function `main':
foo2.cpp:(.text+0x2c): undefined reference to `void func<int>(Foo<int>)'
collect2: error: ld returned 1 exit status

Why is that? And how do I get a function pointer to a function as in #2 above?


Solution

  • template < typename T >
    void func(Foo<T> x);
    

    This declares, but does define, a template function.

    template < typename T >
    class Foo {
        friend void func(Foo) {}
    };
    

    This does not define the template and make it a friend. This effectively defines a non-template function

    void func(foo<T>)
    {
    }
    

    as a friend.

    This is not the same thing as a template function. If you want to reference the template function, then you would do this:

    template < typename T >
    class Foo {
        friend void func<>(Foo);
    };
    

    Just like as in your first example. Now, neither

    func(a);
    

    nor

    (&func)(a);
    

    links, because, of course, you have not defined the template function, in your second case. And once it's defined, you effectively have the same program as your first example.