Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward declaration of template friend function

Consider the following code snippet that works perfectly fine:

class A
{
private:
    int d;
public:
    A(int n){ d = n;}
    friend int foo(A a);
};

int foo(A a)
{
    return a.d;
}

However, when I try to use a template for the class, I need to forward declare the friend function for it to run, as follows:

template <typename T>
class B;

template <typename T>
T foof(B<T> a);


template <typename T>
class B
{
private:
    T d;
public:
    B(T n){ d = n;}
    friend T foof<>(B<T> a);
};

template <typename T>
T foof(B<T> a)
{
    return a.d;
}

Why is the forward declaration necessary in the second example but not on the first one? Also, why do I have to put <> in the declaration of foof inside class B? Why isn't it enough that it is declared inside of the template? I am trying to understand how these things work so that I don't have to blindly memorize this kind of code when I need to use it.

Thanks

like image 516
Cantfindname Avatar asked Sep 24 '16 16:09

Cantfindname


People also ask

Does friend need forward declaration?

Friend Functions For a free function, it is very straightforward and a forward declaration is not required. We can simply declare the friend as follows: The void Print(const Test& test) function has access to the private members of the Test class. For a member function, it's not as straightforward as the free function.

How do you forward a function declaration?

To write a forward declaration for a function, we use a function declaration statement (also called a function prototype). The function declaration consists of the function header (the function's return type, name, and parameter types), terminated with a semicolon. The function body is not included in the declaration.

Can we declare a template function as the friend of the class?

One-to-one: A template function instantiated with one set of template arguments may be a friend to one template class instantiated with the same set of template arguments. This is also the relationship between a regular non-template class and a regular non-template friend function.


2 Answers

Why is the forward declaration necessary in the second example but not on the first one?

Because syntactically the second isn't a form that can be used to declare a function, but the first one is.

Also, why do I have to put <> in the declaration of foof inside class B? Why isn't it enough that it is declared inside of the template?

You're indicating that you're friending a specialization of a function template, as opposed to friending a function that is NOT a template, which is what it would mean otherwise. You can have non-template friend functions of class templates.

like image 95
Barry Avatar answered Nov 15 '22 17:11

Barry


That is because

friend int foo(A a);

is declaration of function and a friend at the same time, but:

friend T foof<>(B<T> a);

Is friend declaration to template instantiation. That's different. Instantiation doesn't declare template function.


You could befriend whole function template, and then forward declaration isn't needed:

template <typename T>
class B
{
private:
    T d;
public:
    B(T n){ d = n;}
    template<class U>
    friend U foof(B<U> a);
};
like image 45
xinaiz Avatar answered Nov 15 '22 19:11

xinaiz