I have a Matrix class with a friend function to use with operator<<. This all works fine but I now want to partially specialize that friend function to work differently if the Matrix class has Matrix as its template parameter (i.e. when the instance of the class has been declared like Matrix< Matrix< char > >). In the class definition first I had
template <typename U>
friend std::ostream& operator<<(std::ostream& output, const Matrix<U>& other);
and I tried adding
friend std::ostream& operator<<(std::ostream& output, const Matrix<Matrix<char> >& other);
but this gave me multiple declaration errors from the compiler.
I can't seem to figure out how to accomplish this.
There's no such thing as a partial specialization of a function template.
You need overloading, not specialization. This should compile, link, and run cleanly (it does for me):
#include <iostream>
template <typename T>
class Matrix {
public:
template <typename U> friend std::ostream&
operator<<(std::ostream& output, const Matrix<U>& other);
friend std::ostream&
operator<<(std::ostream& output, const Matrix<Matrix<char> >& other);
};
template <typename U>
std::ostream&
operator<<(std::ostream& output, const Matrix<U>& other)
{
output << "generic\n";
return output;
}
std::ostream&
operator<<(std::ostream& output, const Matrix<Matrix<char> >& other)
{
output << "overloaded\n";
return output;
}
int main ()
{
Matrix<int> a;
std::cout << a;
Matrix<Matrix<char> > b;
std::cout << b;
}
If you are getting compiler errors from this, you probably have a buggy compiler.
Try writing the specialization explicitly:
template <>
friend std::ostream& operator<< <Matrix<char> >(std::ostream& output,
const Matrix<Matrix<char> >& other);
Related
I have read couple of the questions regarding my problem on StackOverflow.com now, and none of it seems to solve my problem. Or I maybe have done it wrong...
The overloaded << works if I make it into an inline function. But how do I make it work in my case?
warning: friend declaration std::ostream& operator<<(std::ostream&, const D<classT>&)' declares a non-template function
warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
/tmp/cc6VTWdv.o:uppgift4.cc:(.text+0x180): undefined reference to operator<<(std::basic_ostream<char, std::char_traits<char> >&, D<int> const&)'
collect2: ld returned 1 exit status
The code:
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const;
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
template <class classT>
ostream& operator<<(ostream &os, const D<classT>& rhs)
{
os << rhs.d;
return os;
}
This is one of those frequently asked questions that have different approaches that are similar but not really the same. The three approaches differ in who you are declaring to be a friend of your function --and then on how you implement it.
The extrovert
Declare all instantiations of the template as friends. This is what you have accepted as answer, and also what most of the other answers propose. In this approach you are needlessly opening your particular instantiation D<T> by declaring friends all operator<< instantiations. That is, std::ostream& operator<<( std::ostream &, const D<int>& ) has access to all internals of D<double>.
template <typename T>
class Test {
template <typename U> // all instantiations of this template are my friends
friend std::ostream& operator<<( std::ostream&, const Test<U>& );
};
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& ) {
// Can access all Test<int>, Test<double>... regardless of what T is
}
The introverts
Only declare a particular instantiation of the insertion operator as a friend. D<int> may like the insertion operator when applied to itself, but it does not want anything to do with std::ostream& operator<<( std::ostream&, const D<double>& ).
This can be done in two ways, the simple way being as #Emery Berger proposed, which is inlining the operator --which is also a good idea for other reasons:
template <typename T>
class Test {
friend std::ostream& operator<<( std::ostream& o, const Test& t ) {
// can access the enclosing Test. If T is int, it cannot access Test<double>
}
};
In this first version, you are not creating a templated operator<<, but rather a non-templated function for each instantiation of the Test template. Again, the difference is subtle but this is basically equivalent to manually adding: std::ostream& operator<<( std::ostream&, const Test<int>& ) when you instantiate Test<int>, and another similar overload when you instantiate Test with double, or with any other type.
The third version is more cumbersome. Without inlining the code, and with the use of a template, you can declare a single instantiation of the template a friend of your class, without opening yourself to all other instantiations:
// Forward declare both templates:
template <typename T> class Test;
template <typename T> std::ostream& operator<<( std::ostream&, const Test<T>& );
// Declare the actual templates:
template <typename T>
class Test {
friend std::ostream& operator<< <T>( std::ostream&, const Test<T>& );
};
// Implement the operator
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& t ) {
// Can only access Test<T> for the same T as is instantiating, that is:
// if T is int, this template cannot access Test<double>, Test<char> ...
}
Taking advantage of the extrovert
The subtle difference between this third option and the first is in how much you are opening to other classes. An example of abuse in the extrovert version would be someone that wants to get access into your internals and does this:
namespace hacker {
struct unique {}; // Create a new unique type to avoid breaking ODR
template <>
std::ostream& operator<< <unique>( std::ostream&, const Test<unique>& )
{
// if Test<T> is an extrovert, I can access and modify *any* Test<T>!!!
// if Test<T> is an introvert, then I can only mess up with Test<unique>
// which is just not so much fun...
}
}
You can't declare a friend like that, you need to specify a different template type for it.
template <typename SclassT>
friend ostream& operator<< (ostream & os, const D<SclassT>& rhs);
note SclassT so that it doesn't shadow classT. When defining
template <typename SclassT>
ostream& operator<< (ostream & os, const D<SclassT>& rhs)
{
// body..
}
This worked for me without any compiler warnings.
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const {
return (d > rhs.d);
}
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D& rhs) {
os << rhs.d;
return os;
}
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
I think you shouldn't make friend in the first place.
You can create a public method call print, something like this (for a non template class):
std::ostream& MyClass::print(std::ostream& os) const
{
os << "Private One" << privateOne_ << endl;
os << "Private Two" << privateTwo_ << endl;
os.flush();
return os;
}
and then, outside the class (but in the same namespace)
std::ostream& operator<<(std::ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
I think it should work also for template class, but I haven't tested yet.
Here you go:
#include <cstdlib>
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const { return d > rhs.d;};
classT operator=(const D<classT>& rhs);
template<class classT> friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
template<class classT> ostream& operator<<(ostream& os, class D<typename classT> const& rhs)
{
os << rhs.d;
return os;
}
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
I have read couple of the questions regarding my problem on StackOverflow.com now, and none of it seems to solve my problem. Or I maybe have done it wrong...
The overloaded << works if I make it into an inline function. But how do I make it work in my case?
warning: friend declaration std::ostream& operator<<(std::ostream&, const D<classT>&)' declares a non-template function
warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
/tmp/cc6VTWdv.o:uppgift4.cc:(.text+0x180): undefined reference to operator<<(std::basic_ostream<char, std::char_traits<char> >&, D<int> const&)'
collect2: ld returned 1 exit status
The code:
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const;
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
template <class classT>
ostream& operator<<(ostream &os, const D<classT>& rhs)
{
os << rhs.d;
return os;
}
This is one of those frequently asked questions that have different approaches that are similar but not really the same. The three approaches differ in who you are declaring to be a friend of your function --and then on how you implement it.
The extrovert
Declare all instantiations of the template as friends. This is what you have accepted as answer, and also what most of the other answers propose. In this approach you are needlessly opening your particular instantiation D<T> by declaring friends all operator<< instantiations. That is, std::ostream& operator<<( std::ostream &, const D<int>& ) has access to all internals of D<double>.
template <typename T>
class Test {
template <typename U> // all instantiations of this template are my friends
friend std::ostream& operator<<( std::ostream&, const Test<U>& );
};
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& ) {
// Can access all Test<int>, Test<double>... regardless of what T is
}
The introverts
Only declare a particular instantiation of the insertion operator as a friend. D<int> may like the insertion operator when applied to itself, but it does not want anything to do with std::ostream& operator<<( std::ostream&, const D<double>& ).
This can be done in two ways, the simple way being as #Emery Berger proposed, which is inlining the operator --which is also a good idea for other reasons:
template <typename T>
class Test {
friend std::ostream& operator<<( std::ostream& o, const Test& t ) {
// can access the enclosing Test. If T is int, it cannot access Test<double>
}
};
In this first version, you are not creating a templated operator<<, but rather a non-templated function for each instantiation of the Test template. Again, the difference is subtle but this is basically equivalent to manually adding: std::ostream& operator<<( std::ostream&, const Test<int>& ) when you instantiate Test<int>, and another similar overload when you instantiate Test with double, or with any other type.
The third version is more cumbersome. Without inlining the code, and with the use of a template, you can declare a single instantiation of the template a friend of your class, without opening yourself to all other instantiations:
// Forward declare both templates:
template <typename T> class Test;
template <typename T> std::ostream& operator<<( std::ostream&, const Test<T>& );
// Declare the actual templates:
template <typename T>
class Test {
friend std::ostream& operator<< <T>( std::ostream&, const Test<T>& );
};
// Implement the operator
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& t ) {
// Can only access Test<T> for the same T as is instantiating, that is:
// if T is int, this template cannot access Test<double>, Test<char> ...
}
Taking advantage of the extrovert
The subtle difference between this third option and the first is in how much you are opening to other classes. An example of abuse in the extrovert version would be someone that wants to get access into your internals and does this:
namespace hacker {
struct unique {}; // Create a new unique type to avoid breaking ODR
template <>
std::ostream& operator<< <unique>( std::ostream&, const Test<unique>& )
{
// if Test<T> is an extrovert, I can access and modify *any* Test<T>!!!
// if Test<T> is an introvert, then I can only mess up with Test<unique>
// which is just not so much fun...
}
}
You can't declare a friend like that, you need to specify a different template type for it.
template <typename SclassT>
friend ostream& operator<< (ostream & os, const D<SclassT>& rhs);
note SclassT so that it doesn't shadow classT. When defining
template <typename SclassT>
ostream& operator<< (ostream & os, const D<SclassT>& rhs)
{
// body..
}
This worked for me without any compiler warnings.
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const {
return (d > rhs.d);
}
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D& rhs) {
os << rhs.d;
return os;
}
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
I think you shouldn't make friend in the first place.
You can create a public method call print, something like this (for a non template class):
std::ostream& MyClass::print(std::ostream& os) const
{
os << "Private One" << privateOne_ << endl;
os << "Private Two" << privateTwo_ << endl;
os.flush();
return os;
}
and then, outside the class (but in the same namespace)
std::ostream& operator<<(std::ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
I think it should work also for template class, but I haven't tested yet.
Here you go:
#include <cstdlib>
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const { return d > rhs.d;};
classT operator=(const D<classT>& rhs);
template<class classT> friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
template<class classT> ostream& operator<<(ostream& os, class D<typename classT> const& rhs)
{
os << rhs.d;
return os;
}
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
I am trying to overload << operator and using friend function.
Below code chunk works just fine.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
};
Since it is friend function I would obviously want to define it outside the class without using scope resolution operator. But when I try that I get error.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
};
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
Below is the code snippet for main
Mystack<int> intstack;
std::cout << intstack;
ERROR : Unresolved extrernal symbol.
P.S: Its not the complete running code. Just a sample. Kindly bear.
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
declares and befriends a non-template operator<< function. So Mystack<int> would have as its friend a non-template function std::ostream& operator<<(std::ostream& s, Mystack<int> const& d);, etc.
template<class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
defines an operator<< function template.
The two are not the same. When you write std::cout << intstack;, the overload resolution rules resolve it to the non-template operator<< function you declared, but it isn't defined, so you get a linker error.
There's no way to define a non-template function for every instantiation of a class template outside the class template. You can, however, befriend a specialization of your operator<< function template:
// forward declarations
template <class T>
class Mystack;
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
template <class T>
class Mystack
{
friend std::ostream& operator<< <T>(std::ostream& s, Mystack<T> const& d);
// ^^^
};
or befriend every specialization of the function template, which is worse from an encapsulation point of view (since, e.g., operator<< <int> would be a friend of Mystack<float>):
template <class T>
class Mystack
{
public:
template <class U>
friend std::ostream& operator<<(std::ostream& s, Mystack<U> const& d);
};
or just define the friend function inside the class.
I am trying to overload << operator and using friend function.
Below code chunk works just fine.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
};
Since it is friend function I would obviously want to define it outside the class without using scope resolution operator. But when I try that I get error.
template <class T>
class Mystack{
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
};
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
Below is the code snippet for main
Mystack<int> intstack;
std::cout << intstack;
ERROR : Unresolved extrernal symbol.
P.S: Its not the complete running code. Just a sample. Kindly bear.
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
declares and befriends a non-template operator<< function. So Mystack<int> would have as its friend a non-template function std::ostream& operator<<(std::ostream& s, Mystack<int> const& d);, etc.
template<class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d)
{
d.print(s);
return s;
}
defines an operator<< function template.
The two are not the same. When you write std::cout << intstack;, the overload resolution rules resolve it to the non-template operator<< function you declared, but it isn't defined, so you get a linker error.
There's no way to define a non-template function for every instantiation of a class template outside the class template. You can, however, befriend a specialization of your operator<< function template:
// forward declarations
template <class T>
class Mystack;
template <class T>
std::ostream& operator<<(std::ostream& s, Mystack<T> const& d);
template <class T>
class Mystack
{
friend std::ostream& operator<< <T>(std::ostream& s, Mystack<T> const& d);
// ^^^
};
or befriend every specialization of the function template, which is worse from an encapsulation point of view (since, e.g., operator<< <int> would be a friend of Mystack<float>):
template <class T>
class Mystack
{
public:
template <class U>
friend std::ostream& operator<<(std::ostream& s, Mystack<U> const& d);
};
or just define the friend function inside the class.
I have read couple of the questions regarding my problem on StackOverflow.com now, and none of it seems to solve my problem. Or I maybe have done it wrong...
The overloaded << works if I make it into an inline function. But how do I make it work in my case?
warning: friend declaration std::ostream& operator<<(std::ostream&, const D<classT>&)' declares a non-template function
warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
/tmp/cc6VTWdv.o:uppgift4.cc:(.text+0x180): undefined reference to operator<<(std::basic_ostream<char, std::char_traits<char> >&, D<int> const&)'
collect2: ld returned 1 exit status
The code:
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const;
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
template <class classT>
ostream& operator<<(ostream &os, const D<classT>& rhs)
{
os << rhs.d;
return os;
}
This is one of those frequently asked questions that have different approaches that are similar but not really the same. The three approaches differ in who you are declaring to be a friend of your function --and then on how you implement it.
The extrovert
Declare all instantiations of the template as friends. This is what you have accepted as answer, and also what most of the other answers propose. In this approach you are needlessly opening your particular instantiation D<T> by declaring friends all operator<< instantiations. That is, std::ostream& operator<<( std::ostream &, const D<int>& ) has access to all internals of D<double>.
template <typename T>
class Test {
template <typename U> // all instantiations of this template are my friends
friend std::ostream& operator<<( std::ostream&, const Test<U>& );
};
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& ) {
// Can access all Test<int>, Test<double>... regardless of what T is
}
The introverts
Only declare a particular instantiation of the insertion operator as a friend. D<int> may like the insertion operator when applied to itself, but it does not want anything to do with std::ostream& operator<<( std::ostream&, const D<double>& ).
This can be done in two ways, the simple way being as #Emery Berger proposed, which is inlining the operator --which is also a good idea for other reasons:
template <typename T>
class Test {
friend std::ostream& operator<<( std::ostream& o, const Test& t ) {
// can access the enclosing Test. If T is int, it cannot access Test<double>
}
};
In this first version, you are not creating a templated operator<<, but rather a non-templated function for each instantiation of the Test template. Again, the difference is subtle but this is basically equivalent to manually adding: std::ostream& operator<<( std::ostream&, const Test<int>& ) when you instantiate Test<int>, and another similar overload when you instantiate Test with double, or with any other type.
The third version is more cumbersome. Without inlining the code, and with the use of a template, you can declare a single instantiation of the template a friend of your class, without opening yourself to all other instantiations:
// Forward declare both templates:
template <typename T> class Test;
template <typename T> std::ostream& operator<<( std::ostream&, const Test<T>& );
// Declare the actual templates:
template <typename T>
class Test {
friend std::ostream& operator<< <T>( std::ostream&, const Test<T>& );
};
// Implement the operator
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& t ) {
// Can only access Test<T> for the same T as is instantiating, that is:
// if T is int, this template cannot access Test<double>, Test<char> ...
}
Taking advantage of the extrovert
The subtle difference between this third option and the first is in how much you are opening to other classes. An example of abuse in the extrovert version would be someone that wants to get access into your internals and does this:
namespace hacker {
struct unique {}; // Create a new unique type to avoid breaking ODR
template <>
std::ostream& operator<< <unique>( std::ostream&, const Test<unique>& )
{
// if Test<T> is an extrovert, I can access and modify *any* Test<T>!!!
// if Test<T> is an introvert, then I can only mess up with Test<unique>
// which is just not so much fun...
}
}
You can't declare a friend like that, you need to specify a different template type for it.
template <typename SclassT>
friend ostream& operator<< (ostream & os, const D<SclassT>& rhs);
note SclassT so that it doesn't shadow classT. When defining
template <typename SclassT>
ostream& operator<< (ostream & os, const D<SclassT>& rhs)
{
// body..
}
This worked for me without any compiler warnings.
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const {
return (d > rhs.d);
}
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D& rhs) {
os << rhs.d;
return os;
}
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
I think you shouldn't make friend in the first place.
You can create a public method call print, something like this (for a non template class):
std::ostream& MyClass::print(std::ostream& os) const
{
os << "Private One" << privateOne_ << endl;
os << "Private Two" << privateTwo_ << endl;
os.flush();
return os;
}
and then, outside the class (but in the same namespace)
std::ostream& operator<<(std::ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
I think it should work also for template class, but I haven't tested yet.
Here you go:
#include <cstdlib>
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const { return d > rhs.d;};
classT operator=(const D<classT>& rhs);
template<class classT> friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
template<class classT> ostream& operator<<(ostream& os, class D<typename classT> const& rhs)
{
os << rhs.d;
return os;
}
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}