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;
};
Related
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;
};
I am trying to understand how templates and friendship works in C++. So looking/trying out some examples by myself. One such example that i am unable to understand is given below:
VERSION 1
#include <iostream>
using namespace std;
//template<typename T> void func4();
//template<typename T> class NAME;
// template<typename T> std::ostream& operator<< (std::ostream&, NAME<T> const&);
template<typename T>
class NAME {
friend void func4<T>();
friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const&);
};
int main()
{
cout << "Hello World" << endl;
return 0;
}
The above version 1 gives the following error:
prog.cc:13:17: error: variable or field 'func4' declared void
13 | friend void func4<T>();
| ^~~~~
prog.cc:13:17: error: expected ';' at end of member declaration
13 | friend void func4<T>();
| ^~~~~
| ;
prog.cc:13:22: error: expected unqualified-id before '<' token
13 | friend void func4<T>();
| ^
My first question is that even though i have commented the forward declarations for both func4 and operator<< template function, then how can i only get error only for func4? That is why is there no error for operator<<.
Note that i know we need forward declarations if we want to befriend a specific instantiation of a template. That is for
friend void func4<T>();
to work we need to comment out the statement
template<typename T> void func4();
and similarly for
friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const&);
to work we need to comment out corresponding forward declaration at the starting of the program. But when i comment out only template<typename T> void func4(); statement, the program works and and there is no error for operator<<. Again why aren't we getting the error for operator<< even though i have not comment out the corresponding forward declarations.
My second question is that is the statement
friend void func4<T>();
same as
friend void func4<>();
Similarly, is the statement
friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const&);
same as
friend std::ostream& operator<< <> (std::ostream&, NAME<T> const&);
My thinking is that the statement friend void func4<>(); is a specialization of the function template declared using the statement template <typename T> void func4();. Meanwhile when we write friend void func4<T>(); we are explicitly passing T so in this case when we write/call func4<int>(); the function template func4<int> will be intantiated and then occupy memory. On the other hand the specialised template function will already take up some memory since we have to provide its definition before we can call it. So can someone explain whether there is a difference when we use <T> and when we use <>. In summary, it seems to me that in case of <> a user supplied specialization will be used while in case of <T> a new intiantion will be created when we call func4(). So there is a difference because in case of <> we have to supply a definition which will already take some space(memory) while in the case of <T> func4 will only take space(memory) when we use/call it. Is this the correct conclusion?
My third question is that i have read that:
There is no way to explicitly specify template arguments to overloaded operators, conversion functions, and constructors, because they are called without the use of the function name.
According to the above quoted statement we cannot explicitly specify template arguments to overloaded operators, but then how can write friend std::ostream& operator<< <T> (std::ostream&, NAME<T> const&); as it overload operator << .
Answer 1
There is no error for operator<< because you have used using namespace std; and in the std namespace there is already overloaded operator<<.
Answer 3
The quoted statement talks about calling(i.e., using) overloaded operators not defining/declaring them
Answer 2
VERSION 1
#include <iostream>
template<typename T> void func4();
template<typename T>
class NAME {
//friend void func4<>();//this does not work because there is no way to deduce the template arguments
friend void func4<T>();//this works because here we have explicitly passed T as the template argument
};
int main()
{
std::cout << "Hello World" << std::endl;
NAME<int> n;
return 0;
}
In version 1 above we have a function template func4<>. Now when you write friend void func<T>(); and friend void func<>();, you are making the full specialization friend of the class template NAME<>. The reason friend void func<>(); does not work is that there is no way for template argument deduction to work in this case. While when you write friend void func<T>(); you have explicitly passed the template argument and so this works. This also means that both(friend void func<T> and friend void func<>();) are essentially the same specialization of the template function func<>. This will be more clear from my next example version 2.
VERSION 2
#include <iostream>
template<typename T> class NAME;
template<typename T> std::ostream& operator<<(std::ostream&, const NAME<T>& );
template<typename T>
class NAME {
//both of the below friend declarations are equivalent
friend std::ostream& operator<< <T>(std::ostream&, const NAME<T>&);//this works
friend std::ostream& operator<< <>(std::ostream&, const NAME<T>&);//this works as well becasue of template argument deduction
};
int main()
{
std::cout << "Hello World" << std::endl;
NAME<int> n;
return 0;
}
In version 2 above we have an overloaded operator function template. Both friend std::ostream& operator<< <T>(std::ostream&, const NAME<T>&); and friend std::ostream& operator<< <>(std::ostream&, const NAME<T>&); are equivalent and are the same specialization of the overloaded template operator<< <T>. The only difference between them is that the second one uses template argument deduction. This is possible because unlike version 1, we have a function argument that depends on T this time so template argument deduction can work. This was not possible in case of function template func4<> because that function does not take any parameter that depends on the template parameter.
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"
I am getting the following errors- errors whenever i try to compile the following program- http://codepad.org/Bf9l8j9H in VS 2010.
Any idea how to resolve the errors??
That is a linker error, and it indicates that you have declared but not defined (or the definition is not linked) the following overload:
std::ostream& operator<<( std::ostream&, node<weight>& );
The common checks to do from here would be checking whether you have a definition, whether the definition signature matches the declaration (have you declared that, but defined the operator taking a const reference?), whether the definition is being compiled and linked...
I just got a few time and actually read the code, which I will basically condense into this:
template <typename T>
struct node {
friend std::ostream& operator<<( std::ostream&, node<T>& ); // [1] !!!!
};
template <typename T>
std::ostream& operator<<( std::ostream& o, node<T>& n ) {} // [2]
This is a common mistake and one of the reasons why it is simpler just to inline the definition of friend functions inside the templates that befriend them. Basically, in [1] your template is declaring (and befriending) a non-templated function that takes an ostream& and a node<T>& object.
The subtlety here is that when the template is instantiated for some particular type, and the friend declaration is processed, T is fixed and that line befriends a free non-templated function. For example, if you instantiate node with int, as in node<int> n, the compiler will inject int and replace T with it, then the friend declaration will be: friend ostream& operator<<( ostream&, node<int>& ), and that in turn declares a free function in the enclosing namespace. Making that declaration explicit (and assuming that you only instantiate the template with int, your code is read by the compiler as:
template <typename T> struct node {
friend ostream& operator<<( ostream&, node& ); // [1] note <T> not required here
};
// instantiating with int:
ostream& operator<<( ostream&, node<int>& ); // [3] declaration, not definition
template <typename T>
ostream& operator<<( ostream&, node<T>& ) {} // [2] your definition
At this point, whenever you type std::cout << a_int_node; the compiler will consider all overloads, it will find a non-templated free function [3] that is a perfect match, and a templated version [2], but the non-templated version will take precedence. The compiler will not instantiate the templated operator<< and will expect that you manually define the function in one translation unit.
Solutions
Simplest best solution is having the compiler generate the free function for you. You can just provide the operator definition inside the templated class and everything will be nice and simple:
template <typename T>
struct node {
friend std::ostream& operator<<( std::ostream& o, node& n ) // [1]
{ /* code goes here */ return o; }
};
Even if the code is inside the template, because of the friend being there, you are actually declaring and defining the function at namespace level. If you instantiate the template with int, the compiler will generate: std::ostream& operator<<( std::ostream&, node<int>& ) for you in the enclosing namespace.
This solution is the best of all worlds: you only grant access to a single piece of code, and the compiler takes care of most of the gory details.
On the other end, you can befriend a whole template function. The syntax for that would be:
template <typename T>
struct node {
template <typename U>
friend std::ostream& operator<<( std::ostream&, node<U>& ); // [4]
};
template <typename T>
std::ostream& operator<<( std::ostream& o, node<T>& n ) // can access private parts
{ /* code goes here */ return o; }
In this case, you are opening all instantiations of node to all instantiations of the templated function, which semantically is opening the class to other users.
The third option is befriending a single template instantiation, this will have the same effect as the first option with the only difference that instead of a non-templated free function you are using a templated one. On the other hand, the syntax is quite more cumbersome as it requires declaring the function template before befriending, and that in turn requires declaring the class template:
template <typename T> struct node; // forward declare the class template
template <typename T>
std::ostream& operator<<( std::ostream&, node<T>& ); // declare function template
template <typename T>
struct node { // define class template
friend std::ostream& operator<< <>( std::ostream&, node<T>& ); // befriend instantiation
};
template <typename T>
std::ostream& operator<<( std::ostream& o, node<T>& n ) // define function template
{ ... }
As you see, the simplest best solution is just defining the function template inside the class definition.
conio.h is an old header from the MS-DOS compilers; UPDATE: it is still available in VS 2010, though.
best is a stream you declared after you used it.
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.