C++ friend template function - minGW error but not VS2015 - c++

The following code compiles without a problem with Visual Studio 2015 but with minGW gets the warning and error shown below it:
#include <iostream>
using std::ostream;
template<typename ElemType, int SIZE>
class Array
{
friend ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value);
ElemType operator[](int index) const;
private:
ElemType elements[SIZE];
};
template<typename ElemType, int SIZE>
ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value);
template<typename ElemType, int SIZE>
ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value)
{
out << elements[0];
return out;
}
mingw32-g++.exe -Wall -g -pedantic-errors -pedantic -Wextra -Wall -std=c++98 -c Test.cpp
Test.cpp:7:79: warning: friend declaration 'std::ostream& operator<<(std::ostream&, const Array<ElemType, SIZE>&)' declares a non-template function [-Wnon-template-friend]
Test.cpp:7:79: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
Test.cpp: In function 'std::ostream& operator<<(std::ostream&, const Array<ElemType, SIZE>&)':
Test.cpp:21:11: error: 'elements' was not declared in this scope
I'm far from an expert on some of this stuff so I'm not sure what the issue is. It seems like it's telling me it needs the follwoing code just before the friend declaration in the class itself, but when I put it there it causes other compilation errors:
template<typename ElemType, int SIZE>
Thanks in advance!
After making the changes suggested by #Trevor Hickey in his post below the warning about the friend template function went away. However, I still get the error about "elements" (in the friend function) not being declared in scope.

There's two separate problems in your code. The easier one is that out << elements[0]; should be out << value.elements[0];. This is because you want to print the element that is a member of the parameter value. Remember that we are in a non-member function here, there is no this and no members you can access by unqualified name.
The other one is known as the template friends problem. So far you only get a warning, but if you try to compile a complete program you get an error. I added the code:
int main() { Array<int, 5> a; std::cout << a; }
and the error appears:
undefined reference to `std::ostream& operator<< <int, 5>(std::ostream&, Array<int, 5> const&)'
The problem is that your code:
friend ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value);
actually declares that there is a non-template function which will be the friend to this instance of Array. Later, when you write cout << a in main, the compiler matches that << to this non-template declaration. It never gets so far as the body for operator<< that you provided later, and so never instantiates a copy of that body, hence the undefined reference error.
One way to fix this is to explicitly instantiate the body. But this is lame as you'd have to write an explicit instantiation for each possible instantiateion of Array that occurs for your code. So we won't do this.
The simplest solution is to put the body of operator<< inline in the class definition.
The other option is to declare that operator<< is a template function.
Trevor Hickey's code shows one way of doing this, although that has a drawback that Array<A, B>::elements can be accessed by Array<C, D>::operator<<.
A more secure way is to declare the operator<< before the class:
template<typename ElemType, int SIZE>
class Array;
template<typename ElemType, int SIZE>
ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value);
and then the rest of your code as it was before. Now, the friend declaration in the class will match the pre-existing template, instead of declaring a new non-template.

You are using the template paramters from the class, but the function itself is not a template function. It needs to be a template function as seen in the definition.
#include <iostream>
using std::ostream;
template<typename ElemType, int SIZE>
class Array
{
template<typename T, int U>
friend ostream &operator<<(ostream &out, const Array<T, U> &value);
ElemType operator[](int index) const;
private:
ElemType elements[SIZE];
};
template<typename ElemType, int SIZE>
ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value)
{
out << value.elements[0];
return out;
}

Related

Unnresolved externals [duplicate]

I have a problem to overload the << stream operator and I don't find the solution :
template<class T, unsigned int TN>
class NVector
{
inline friend std::ostream& operator<< (
std::ostream &lhs, const NVector<T, TN> &rhs);
};
template<class T, unsigned int TN>
inline std::ostream& NVector<T, TN>::operator<<(
std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};
It produces the following error message:
warning : friend declaration ‘std::ostream& operator<<(std::ostream&, const NVector&)’ declares a non-template function [-Wnon-template-friend]
error: ‘std::ostream& NVector::operator<<(std::ostream&, const NVector&)’ must take exactly one argument
How to solve that problem ?
Thank you very much.
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 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;
};

C++ Templates and a Linker Error

Please consider the following C++ program:
#include <iostream>
using namespace std;
template <class T> class Array
{
T *pType;
int itsSize;
public:
// template <class T>
friend ostream &operator<< (ostream &, Array<T> & );
};
template <class T>
ostream &operator<< (ostream &output, Array<T> &theArray)
{
return (output);
}
ostream &operator<< (ostream &, Array<int> &);
int main ()
{
Array<int> theArray;
cout << theArray << endl;
return 0;
}
The above code compiles but the linker gives the following error:
undefined symbol `operator<<(std::ostream&, Array&)'
I believe I need to tell the compiler to instantiate a function for the operator << but I do not know how to do that.
Bob
No, you don't need to tell the compiler to instantiate a template, it does that all by itself, if and when needed.
Your line
ostream &operator<< (ostream &, Array<int> &);
actually tells the compiler that you have some other operator for Array<int> so that it shouldn't use the template for that type.
So the linker goes looking for this other operator, but of course doesn't find any.
If you just remove that extra declaration, it should work much better.
The declaration
ostream &operator<< (ostream &, Array<int> &);
is not telling the compiler to instantiate the template. It is declaring a separate and distinct non-templated function i.e. overloading.
Within main(), the usage of operator<<() resolves to the declared function. The compiler does not need to specialize the template to find a match. However, since there is no definition (i.e. implementation) of that function, the linking fails.
Remove that declaration and you should find that your code compiles and links.
Incidentally, output streaming operators generally don't change the object being output. It is therefore advisable to change the templated ostream &operator<< (ostream &, Array<T> & ) to be ostream &operator<< (ostream &, const Array<T> & )
Also, since templates (typically) need to be defined in header files, and header files are included in multiple source files, it is better to avoid using namespace std, and replace ostream with std::ostream.
There are issues with your code, #BoPersson and #Perter pointed out some.
But even if you change what they suggested (Here is a live demo on ideone) and I ran it on my VS 2015 too. The compilers are still mad.
Ideone says:
prog.cpp:10:55: warning: friend declaration 'std::ostream& operator&)' declares a non-template function [-Wnon-template-friend]
friend ostream &operator & );
^
prog.cpp:10:55: note: (if this is not what you intended, make sure the function template has already been declared and add after the function name here)
/home/FHMhT9/ccNwcxP0.o: In function `main':
prog.cpp:(.text.startup+0x1b): undefined reference to `operator&)'
collect2: error: ld returned 1 exit status
And VS gives the pretty much same errors too.
Ideone is telling me, that the friend declaration in the class declares a non-template function.
So, change the declaration in the class to:
friend ostream &operator<< <T> (ostream &, Array<T> & );
// ^^^^^
// I added this <T> to tell the compiler that it is a template function.
But you need to define the function before this, so cut the implementation of operator<< and then paste it before the class. But you'd need a forward declaration of the class for that to work. So finally your code becomes pretty much like this:
And I changed the Array<T> & to const Array<T> & too.
#include <iostream>
template <typename T>
class Array;
template <class T>
std::ostream &operator<< (std::ostream &output, const Array<T> &theArray)
{
output << "abc";
return (output);
}
template <class T> class Array
{
T *pType;
int itsSize;
public:
// template <class T>
friend std::ostream &operator<< <T> (std::ostream &, const Array<T> &);
};
int main()
{
Array<int> theArray;
std::cout << theArray << std::endl;
return 0;
}
and this version now works.

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

I have a problem to overload the << stream operator and I don't find the solution :
template<class T, unsigned int TN>
class NVector
{
inline friend std::ostream& operator<< (
std::ostream &lhs, const NVector<T, TN> &rhs);
};
template<class T, unsigned int TN>
inline std::ostream& NVector<T, TN>::operator<<(
std::ostream &lhs, const NVector<T, TN> &rhs)
{
/* SOMETHING */
return lhs;
};
It produces the following error message:
warning : friend declaration ‘std::ostream& operator<<(std::ostream&, const NVector&)’ declares a non-template function [-Wnon-template-friend]
error: ‘std::ostream& NVector::operator<<(std::ostream&, const NVector&)’ must take exactly one argument
How to solve that problem ?
Thank you very much.
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 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;
};

How do you declare the friend of a generic class outside of the class decleration?

The following code works, but i would like to move ostream& operator<< outside of the class declearation as i have with hash::operator[].
#include<iostream>
#include<map>
using namespace std;
template <class T>
class hash {
private:
map<string, T> _map;
public:
T& operator[] (string x);
friend ostream& operator<<(ostream& out, const hash<T> &rhs) { return out << "test"; }
};
template <class T>
T & hash<T>::operator[](string x) {
return _map[x];
}
int main () {
hash<int> myobject;
myobject["a"] = 1;
cout << myobject["a"] << endl;
cout << myobject << endl;
return 0;
}
I have tried:
template <class T>
ostream& operator<<(...) {
return out << "test";
}
and
ostream& operator<<(...) {
return out << "test";
}
as well as a few other combinations to no avail.
Since it does not seem that this question is getting closed as exact duplicate, I will explain what your program does.
template <typename T>
class test {
int private_field;
friend std::ostream& operator<<( std::ostream&, test<T> const & );
};
// ???
int main() {
std::cout << test<int>() << std::endl;
}
Templates are instantiated on demand (unless you explicitly instantiate them), that means that in this particular program test is instantiated only as test<int>. When the compiler instantiates the template (because it was requested in main) it will process the template definition. At this point the behavior is similar to rewriting the code with the substituted type at the point of definition (in this case right before main):
class test<int> {
friend std::ostream& operator<<( std::ostream&, test<int> const & );
};
Now, if you look at the instantiated template, you can note that the friend declaration is befriending a non templated function. So in this particular program you can fill in the ??? with that particular function:
std::ostream& operator<<( std::ostream& o, test<int> const & t ) {
return o << t.private_field;
}
The problem here is that this is not easily extensible. The code of that operator<< is the same for test<int> than it is for test<double>, so there should be no need to rewrite the same function for all instantiating types!
At this point there are two options, the first one is, as you have already identified, providing the definition of the function inside the class. The compiler will then process and define the function whenever the type is being instantiated. This solution creates non-templated functions on demand for each template instantiation (which is the option I would do, even with the quirks and strangeness of lookup here).
Now, if you really want to avoid providing the definition inside the templates class, and you still want to provide a single implementation, then you have to resort to providing a templates operator<<. At this point you have two different options, you can declare all instantiations of the template (which I don't quite like, as it opens to too many others), or you can befriend a single specialization of the template function (cleaner regarding access, more cumbersome to write).
The first case is:
template <typename T>
class test {
template <typename U>
friend std::ostream& operator<<( std::ostream&, test<U> const & );
};
template <typename T>
std::ostream& operator<<( std::ostream&, test<T> const & ) { ... }
The second case requires a couple of forward declarations:
template <typename T> test;
template <typename T> std::ostream& operator<<( std::ostream&, test<T> const & );
template <typename T>
class test {
friend std::ostream& operator<< <T>( std::ostream&, const test<T>& );
};
template <typename T>
std::ostream& operator<<( std::ostream&, test<T> const & ) { ... }
There is of course another option: do not declare friends at all. Provide a print(std::ostream&) public function in your class that has the implementation, and provide a non-templated operator<< that just calls print on the second argument.
You have to be careful when you use friend and template
#include<iostream>
#include<map>
template <class T>
class MyHash{
public:
// ... use your T template here
template <class U>
friend ostream& operator<<(ostream& out, const MyHash<U> &rhs);
};
// ...
template <class U>
ostream& operator<<(ostream& out, const MyHash<U> &rhs){ return out << "test"; }
you need to use a different template U because operator<< is a friend method (external), if we use T instead of U, we will have : ambiguous definition in template .
Change hash by MyHash to avoid ambiguities.
Edit :
The error that you get here is :
error C2676: '<' binaire : 'std::string' ne définit pas cet opérateur
ou une conversion vers un type acceptable pour l'opérateur prédéfini
because you forgot to include <string> in "hash.h". That header defines the < operator.
And also try moving the definition of operator[] and operator<< directly into "hash.h"
Both the declaration and definition of templates must be included. This is because in some compilers template functions cannot be compiled and linked independently, since they are generated on request for the specific types they are instantiated with.
Change the #include "hash.cpp" to #include "hash.h"

template class and insertion extraction overloaded

How can I make the insertion (<<) and/or extraction (>>) operator overloaded in a template class WITHOUT making it inline. I would like to have the << or >> operator as a friend class.
I know how to make it inline
example of inline in a matrix class
friend ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
...
// create the ostr
return ostr;
}
but I'd like to have the code outside of the templateclass definition.
g++ told me to add <> after the function name so I did but when I tried to instansiate a matrix of type SOMETYPE it gave me an error that it didn't know how to extract or insert for that type.
If you really want to define the operator externally and befriend only the operator instantiation that coincides in type with this template instantiation, the correct syntax is:
template <typename T> class test; // forward declare template class
template <typename T> // forward declare the templated operator
std::ostream& operator<<( std::ostream&, test<T> const & );
template <typename T>
class test { // define the template
friend std::ostream& operator<< <T>( std::ostream&, test<T> const & ); // befriend
};
template <typename T> // define the operator
std::ostream& operator<<( std::ostream& o, test<T> const & ) {
return o;
}
In most cases it is not worth the hassle to pull the definition out of the class, considering that you still need to provide it in a header and the extra work required.
Also note that there are slight differences for the compiler regarding lookup. In the case where the function is inlined inside the class definition, the compiler will not find that function unless one of the arguments is actually of the type of the template, so it effectively reduces the visibility and the amount of work that the compiler has to do (if the templated operator<< is defined outside of the class, the compiler will find it as a candidate for overload resolution in all places where it finds a << b, only to discard it in all cases where the second argument is not a test<T> (and it will show the templated operator as a candidate in all error messages where it cannot match operator<<, which is a long enough list already).
Try something like:
template <typename T> class Matrix;
template <typename T> std::ostream& operator<<(std::ostream& ostr, const Matrix<T>& m);
template <Typename T>
class Matrix
{
public:
friend ostream& operator<< <T> (ostream& ostr, const Matrix<K>& inputMatrix);
};
// This must be in the same translation unit as the class definition!
template<typename T>
ostream& operator<<(ostream& ostr, const Matrix<T>& inputMatrix)
{
// ...
return ostr;
}
Translation unit reference
re-re-edited to addressed the comments made by aschepler and dribeas.
Place the code in the header, outside the class definition. Or, place it in a .tcc file and include it at the bottom of the header.