template class and insertion extraction overloaded - c++

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.

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++ : 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"

How to resolve the following errors?

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.

signature output operator overload

do you know, how to write signature of a function or method for operator<< for template class in C++? I want something like:
template <class A> class MyClass{
public:
friend ostream & operator<<(ostream & os, MyClass<A> mc);
}
ostream & operator<<(ostream & os, MyClass<A> mc){
// some code
return os;
}
But this just won't compile. Do anyone know, how to write it correctly?
All the below said, if you don't need an operator to be a friend, then don't make it a friend. For output operators in particular, in my opinion you should not make them friends. That is because if your class can be output to a stream, it should have equivalent get functions that provide the same data programmatically. And in that event, you can write a operator<< as a non-friend in terms of those get functions.
In case you have some good reason for making them friends, you can do a friend definition
template <class A> class MyClass {
public:
friend ostream & operator<<(ostream & os, MyClass<A> const& mc) {
// ...
}
};
That way you don't need the template<...> clause that gets you the type A. It's alreay known if you define the operator inside the template. Note that even though you defined it inside the template, it's not a member function. It's still a non-member, but has access to the names declared in the class (like the template parameter). For each instance of MyClass you create, a different non-template operator function is created out of that friend function that prints things.
If you want to define the template outside, you have to predeclare it to be able to declare a given specialization of it as a friend.
// predeclare it so you can make it a friend.
template <class A> class MyClass;
template <class A> ostream &operator<<(ostream &os, MyClass<A> const&);
template <class A> class MyClass{
public:
/* the "<A>" is needed - it says that a given instantiation of
that template is a friend, and not a non-template function. */
friend ostream & operator<< <A>(ostream & os, MyClass<A> const& mc);
};
template <class A>
ostream & operator<<(ostream & os, MyClass<A> const& mc){
// some code
return os;
}
That makes operator<< <Foo> a friend of MyClass<Foo>. If you were to omit the <A> or an also possible empty <>, the compiler would understand that as saying you made a non-template operator having concrete instead of templated parameters as friend.
The more easy but less "correct" solution is to make MyClass <Foo> have as friend all the operator << instantiations. So theoretically operator << <Bar> could access private members of MyClass <Foo>. It's not what is wanted, but it works too, gaining more access than needed. It gets rid of the need for forward declaring:
template <class A> class MyClass{
public:
/* make all instantiations friends. */
template<typename T>
friend ostream & operator<<(ostream & os, MyClass<T> const& mc);
};
template <class T>
ostream & operator<<(ostream & os, MyClass<T> const& mc){
// some code
return os;
}