0

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?

Sören
  • 1,803
  • 2
  • 16
  • 23
  • 1
    Not sure if [this](https://stackoverflow.com/questions/18792565/declare-template-friend-function-of-template-class) would be a dup. – 1201ProgramAlarm Aug 18 '19 at 17:20

1 Answers1

2
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.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • I still don't quite get the difference. How is ```cpp void func(foo) { } ``` not a template? It depends on T, doesn't it? – Sören Aug 18 '19 at 17:15
  • You can have an ordinary function that takes a `foo` parameter, just like an ordinary function that takes an `int` as a parameter. Which is different than an instance of a template function. – Sam Varshavchik Aug 18 '19 at 17:21