Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to give a friend function a default argument while separating declaration and definition

Tags:

c++

I have a function template that I'm declaring as a friend of my class. The thing is, I want to keep the declaration and definition separate because I don't want to clutter the body of X, but I'm running into problems when using the default argument of T():

struct X
{
    template <class T>
    friend void f(T t);
};

template <class T>
void f(T t = T()) {}

// error: default arguments cannot be added to a function template that has
// already been declared
// void f(T t = T()) {}
//          ^   ~~~
// main.cpp:9:17: note: previous template declaration is here
//     friend void f(T t);
//                 ^

If I switch it around to use default arguments in the declaration instead, then the compiler outputs a message saying I have to define the function there, but I don't want to do that.

How do I give a default argument to a friend function template while keeping the definition and declaration separate?

like image 949
user2030677 Avatar asked Mar 18 '23 00:03

user2030677


2 Answers

For function templates you may only write the default arguments in the first declaration in any given scope; and, indeed, there is another rule that prohibits writing the default arguments in the friend declaration:

[C++11: 8.3.6/4]: For non-template functions, default arguments can be added in later declarations of a function in the same scope. [..] If a friend declaration specifies a default argument expression, that declaration shall be a definition and shall be the only declaration of the function or function template in the translation unit.

However, there's nothing stopping you from adding yet another declaration, this time not a friend declaration, before everything else, and put your default arguments on that.

So, in order:

  1. Declaration of function template, with default arguments
  2. Class definition with friend declaration
  3. Definition of function template
like image 76
Lightness Races in Orbit Avatar answered Apr 28 '23 21:04

Lightness Races in Orbit


I think if you declare the template function before friending it that would work, but I can't figure out what your main.cpp has to test. Did you try this (EDIT: this seems to work on coliru but I can't test your real-world scenario).

template <class T>
void f(T t = T());

struct X
{
    template <class T>
    friend void f(T t);
};

template <class T>
void f(T t) {}
like image 42
Mark B Avatar answered Apr 28 '23 22:04

Mark B