Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the rationale behind the syntax chosen to declare template friends?

Declaring template function friends involves some incredibly unintuitive syntax, even for C++! What is the rationale behind the choice of syntax for the extra <> needed? Wouldn't it make more sense to use the template keyword?

For those that don't know about this, here is an example of what you might try to do:

template <typename T>
class Foo
{
  int x;
  friend void bar(Foo<T>);
};

template <typename T>
void bar(Foo<T> f)
{
  std::cout << f.x;
}

If you try to call bar(Foo<T>()), you will get linker errors.

To solve this, you have to forward declare bar (and therefore Foo) and then stick an oddly placed <> in the friend declaration.

template <typename T> class Foo;
template <typename T> void bar(Foo<T>);

template <typename T>
class Foo
{
  int x;
  friend void bar<>(Foo<T>); // note the <> (!?)
};

template <typename T>
void bar(Foo<T> f)
{
    std::cout << f.x;
}

My question is, what is the rationale behind the <> syntax? Wouldn't it be more intuitive to use the template keyword or something along those lines?

EDIT: To clarify, I already know why the <> is required, what I want to know is why they chose to use <> to disambiguate it instead of some other more intuitive syntax.

like image 318
Peter Alexander Avatar asked Jul 23 '11 20:07

Peter Alexander


2 Answers

Wait. You are not declare a friend template. You declare a specialization of a template as friend! As such, why would you want to put a template clause there?

The syntax to name specializations of function templates is by teplateName<ArgumentList>, and that is what you shall use according to the Standard in the friend declarations.

If you want to befriend the whole template and all specializations generated and explicitly specialized, you can still do that, and then you can use a template clause

template<typename U>
friend void bar(Foo<U>);
like image 174
Johannes Schaub - litb Avatar answered Sep 30 '22 01:09

Johannes Schaub - litb


Quoting this page:

The non-template function is called because a non-template function takes precedence in overload resolution.

So my guess the friend void bar<>(Foo<T>); is intuitive because you want to make sure it's the template function you are calling and not an overload for Foo<T>. There would otherwise no way for the compiler to notice if the templated or the non-templated function is the class'es friend.

Why the <> syntax is used and not the template syntax is not clear to me.

like image 40
orlp Avatar answered Sep 30 '22 01:09

orlp