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:
- declare the
operator<<
template as a friend (will grant access to any and all instantiations of the template), - declare a particular instantiation of that template as a friend (more cumbersome to write) or
- avoid friendship altogether providing a public
print( std::ostream& )
member function and calling it from a non-friend templatedoperator<<
. 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; becauseprocess
does not have explicit
template-arguments, each specialization of the task class template has
an appropriately typed functionprocess
as a friend, and this friend
is not a function template specialization; because the friend
preempt
has an explicit template-argumentT
, each specialization
of thetask
class template has the appropriate specialization of the
function templatepreempt
as a friend; and each specialization of
thetask
class template has all specializations of the function
templatefunc
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
templatefrd
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
How to Make Template Rvalue Reference Parameter Only Bind to Rvalue Reference
Where Are Member Functions Stored for an Object
Differencebetween C-Like Casting and Functional Casting
Assembly Adc (Add with Carry) to C++
Is There an Automatic Noexcept Specifier
Is There a Reference_Wrapper<> for Rvalue References
Overriding Static Variables When Subclassing
Why Are Arguments Which Do Not Match the Conversion Specifier in Printf Undefined Behavior
C++11 "Overloaded Lambda" with Variadic Template and Variable Capture
Understanding the List Operator (%) in Boost.Spirit
How to Create a Type in C++ That Takes Less Than One Byte of Memory
Static Control Background Color with C++
Differencebetween Cout, Cerr, Clog of iOStream Header in C++? When to Use Which One
Is Python Faster and Lighter Than C++
Does a C/C++ Compiler Optimize Constant Divisions by Power-Of-Two Value into Shifts