C++:Friend Declaration 'Declares a Non-Template Function

friend declaration declares a non-template function

It sounds like you want to change:

friend ostream& operator << (ostream& out, const Base<T>& e);

To:

template<class T>
friend ostream& operator << (ostream& out, const Base<T>& e);

How to fix gcc warning friend declaration declares a non-template function

The second snippet is ill-formed, because a friend declaration cannot be a definition of a template specialization. An open clang bug report for accepting this is here.

The first one seems valid to me.

The warning by GCC is annoying, because defining a non-template function as friend is what you want to do here. Unfortunately I don't think there is any way to indicate in code that this is really what you want to do, but you can disable the warning with -Wno-non-template-friend. According to the documentation it is there for historical reasons, to identify pre-ISO-C++ compatibility issues where the syntax had a different meaning.

You should be aware that the ability to use friend injections of this kind to enable stateful metaprogramming may be considered unintended feature of the language and could maybe (I don't know) be restricted at some point in the future, see this question.

C++ : friend declaration ‘declares a non-template function

There are two different issues in your code, the first is that the friend declaration (as the warning clearly says, maybe not so clear to understand) declares a single non-templated function as a friend. That is, when you instantiate the template NVector<int,5> it declares a non-templated function std::ostream& operator<<(std::ostream&,NVector<int,5>) as a friend. Note that this is different from declaring the template function that you provided as a friend.

I would recommend that you define the friend function inside the class definition. You can read more on this in this answer.

template <typename T, unsigned int TN>
class NVector {
friend std::ostream& operator<<( std::ostream& o, NVector const & v ) {
// code goes here
return o;
}
};

Alternatively you can opt for other options:

  1. declare the operator<< template as a friend (will grant access to any and all instantiations of the template),
  2. declare a particular instantiation of that template as a friend (more cumbersome to write) or
  3. avoid friendship altogether providing a public print( std::ostream& ) member function and calling it from a non-friend templated operator<<. I would still opt to befriend the non-template function an provide the definition inside the templated class.

The second issue is that when you want to define an operator outside of the class of the left hand side argument, the operator is a free function (not bound to a class) and thus it should not be qualified:

template<class T, unsigned int TN>
inline std::ostream& operator<<(std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};

friend and template in C++

In friend declaration operator<< refers to a non-template function, while its definition says it's a template function; they don't match.

You can define it inline with the friend declaration (as non-template function):

template<class T>
class Matrix {
... ...
friend std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix) {
int dimension = matrix.getDimension();

for(int x = 0; x < dimension; x++) {
for(int y = 0; y < dimension; y++) {
output << matrix.get(x, y) << " ";
}
return output;
}
}
... ...
};

Or make the friend declaration referring to the function template:

// class declaration
template<class T>
class Matrix;

// function declaration
template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix);

// class definition
template<class T>
class Matrix {
... ...
friend std::ostream& operator<< <T>(std::ostream& output, const Matrix<T>& matrix);
... ...
};

// function definition
template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix) {
int dimension = matrix.getDimension();

for(int x = 0; x < dimension; x++) {
for(int y = 0; y < dimension; y++) {
output << matrix.get(x, y) << " ";
}
return output;
}
}

And about the undefined reference error, see Why can templates only be implemented in the header file?

define non-template function outside a templated class

In the first program

template<typename T>
class cl
{
private :
T val;
public:
cl()= default;
explicit cl(T v) : val(std::move(v)) {}

friend void non_template_friend(cl m);
};

template <typename T>
void non_template_friend(cl<T> m) { std::cout << m.val << std::endl;}

You declared a non-template friend funcrion but then you declared and defined a template function with the same name/

A non-template friend function declaration means thatf you have to provide a set of overloaded non-template functions for specializations of the template class/

Here is a demonstrative program.

#include <iostream>
template<typename T>
class cl
{
private :
T val;
public:
cl()= default;
explicit cl(T v) : val(std::move(v)) {}

friend void non_template_friend(cl m) ;
};

void non_template_friend( cl<int> m) { std::cout << m.val << std::endl;}
void non_template_friend( cl<double> m) { std::cout << m.val << std::endl;}

int main()
{
cl<int> c(10);
non_template_friend(c);

cl<double> c2( 20.2 );
non_template_friend(c2);

return 0;
}

The program output is

10
20.2

That is in a template class a non-template friend function declaration is in fact declares a set of overloaded non-template functions.

Friend function with a definition - template or non-template?

It is not a template, because its declaration is not that of a template (even though it appears inside a template declaration itself).

[temp.friend] (emphasis mine)

1 A friend of a class or class template can be a function template
or class template, a specialization of a function template or class
template, or a non-template function or class. For a friend function
declaration that is not a template declaration
:

  • if the name of the friend is a qualified or unqualified template-id, the friend declaration refers to a specialization of a function
    template, otherwise,

  • if the name of the friend is a qualified-id and a matching non-template function is found in the specified class or namespace,
    the friend declaration refers to that function, otherwise,

  • if the name of the friend is a qualified-id and a matching function template is found in the specified class or namespace, the friend
    declaration refers to the deduced specialization of that function
    template ([temp.deduct.decl]), otherwise,

  • the name shall be an unqualified-id that declares (or redeclares) a non-template function.


[ Example:

template<class T> class task;
template<class T> task<T>* preempt(task<T>*);

template<class T> class task {
friend void next_time();
friend void process(task<T>*);
friend task<T>* preempt<T>(task<T>*);
template<class C> friend int func(C);

friend class task<int>;
template<class P> friend class frd;
};

Here, each specialization of the task class template has the function
next_­time as a friend; because process does not have explicit
template-arguments, each specialization of the task class template has
an appropriately typed function process as a friend, and this friend
is not a function template specialization
; because the friend
preempt has an explicit template-argument T, each specialization
of the task class template has the appropriate specialization of the
function template preempt as a friend; and each specialization of
the task class template has all specializations of the function
template func as friends. Similarly, each specialization of the
task class template has the class template specialization
task<int> as a friend, and has all specializations of the class
template frd as friends.  — end example ]

While examples are non-normative, the one in the quote clarifies the intent of the preceding normative text. Since the friend operator declaration is not a template declaration, the text in bold applies. It therefore declares a non-template function.

c++ non-template class friends to a member of template class

You're declaring a nested class template PItem inside Obj, then the friend declaration refers to it, not the one defined in globle scope.

You should remove the nested class template declaration, and move the definition of PItem before the definition of Obj; because the friend declaration requires PItem to be complete type.

template<typename T>
class PItem
{
public:
PItem(T* t) { ptr = t; }
~PItem() {}
int getValue() {
if (ptr) return ptr->getValue();
return -1;
}
T* ptr;
};

class Obj : public ObjBase
{

template<class T>
friend int PItem<T>::getValue();

public:
Obj(int i) { value = i; };
~Obj() {};

private:
int getValue()
{
return value;
}
};

LIVE



Related Topics



Leave a reply



Submit