I tried to separate the declaration and definition of my templated member function of a templated class, but ended up with the following error and warning.
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu);
};
std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu){
for (auto integer : bu._integers){
out<<integer<<std::endl;
}
return out;
}
../hw06/bigunsigned.h:13:77: warning: friend declaration
'std::ostream& operator<<(std::ostream&, const BigUnsigned&)'
declares a non-template function [-Wnon-template-friend]
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu);
^ ../hw06/bigunsigned.h:13:77: note: (if this is not what you
intended, make sure the function template has already been declared
and add <> after the function name here) ../hw06/bigunsigned.h:16:51:
error: invalid use of template-name 'BigUnsigned' without an argument
list std::ostream& operator<<(std::ostream& out, const BigUnsigned&
bu){
^ ../hw06/bigunsigned.h: In function 'std::ostream&
operator<<(std::ostream&, const int&)': ../hw06/bigunsigned.h:17:28:
error: request for member '_integers' in 'bu', which is of non-class
type 'const int'
for (auto integer : bu._integers){
^
When I joined the declaration and definition like this, everything compiles fine.
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu){
for (auto integer : bu._integers){
out<<integer<<std::endl;
}
return out;
}
};
The purpose was to print member variable _integers to cout. What might be the problem?
P.S.: Using this question I made the function free, but did not help.
BigUnsigned is a template type so
std::ostream& operator<<(std::ostream& out, const BigUnsigned& bu)
Will not work as there is no BigUnsigned. You need to make the friend function a template so you can take different types of BigUnsigned<some_type>s.
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
template<typename T>
friend std::ostream& operator<<(std::ostream& out, const BigUnsigned<T>& bu);
};
template<typename T>
std::ostream& operator<<(std::ostream& out, const BigUnsigned<T>& bu){
for (auto integer : bu._integers){
out<<integer<<std::endl;
}
return out;
}
The reason the second example works is that since it is declared inside the class it uses the template type that the class uses.
A refinement to the answer by NathanOliver.
With the other answer, all instantiations of the function template are friends of all instatiations of the class template.
operator<< <int> is a friend of BigUnsigned<int> as well as BigUnsigned<double>.
operator<< <double> is a friend of BigUnsigned<double> as well as BigUnsigned<FooBar>.
You can change the declarations a little bit so that
operator<< <int> is a friend of BigUnsigned<int> but not of BigUnsigned<double>.
operator<< <double> is a friend of BigUnsigned<double> but not BigUnsigned<FooBar>.
// Forward declaration of the class template.
template <typename I> class BigUnsigned;
// Forward declaration of the function template
template <typename I>
std::ostream& operator<<(std::ostream& out, const BigUnsigned<I>& bu);
// Change the friend-ship declaration in the class template.
template <typename I>
class BigUnsigned{
const size_t cell_size=sizeof(I);
std::vector<I> _integers;
public:
BigUnsigned();
BigUnsigned(I);
// Grant friend-ship only to a specific instantiation of the
// function template.
friend std::ostream& operator<< <I>(std::ostream& out, const BigUnsigned<I>& bu);
};
To add a third variant that improves the readability a little bit, is to define the friend function inside the class:
#include <iostream>
template <typename T>
class Foo {
int test = 42;
// Note: 'Foo' inside the class body is basically a shortcut for 'Foo<T>'
// Below line is identical to: friend std::ostream& operator<< (std::ostream &os, Foo<T> const &foo)
friend std::ostream& operator<< (std::ostream &os, Foo const &foo) {
return os << foo.test;
}
};
int main () {
Foo<int> foo;
std::cout << foo << '\n';
}
Related
I checked the answers to this question: Overloading operator<< for a templated class, but unfortunately nothing is working for me so far. Meaning, the compiler is constantly throwing myriad errors at me.
#include <iostream>
namespace usr {
// Forward declarations
template <typename T> class A;
template <typename T>
std::ostream& operator<<(std::ostream& os, const usr::A<T>&);
template <typename T>
class A {
public:
friend std::ostream& operator<<(std::ostream& os,
const usr::A<T>& a);
};
template <typename T>
std::ostream& operator<<(std::ostream& os, const usr::A<T>& a) {
os << "test";
return os;
}
}
int main() {
usr::A<int> a;
std::cout << a << std::endl;
return 0;
}
The error I get:
$ g++ -std=c++11 test.cpp && ./a.out
test.cpp:15:67: warning: friend declaration ‘std::ostream& usr::operator<<(std::ostream&, const usr::A<T>&)’ declares a non-template function [-Wnon-template-friend]
const usr::A<T>& a);
^
test.cpp:15:67: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
/tmp/ccklebu2.o: In function `main':
test.cpp:(.text+0x24): undefined reference to `usr::operator<<(std::ostream&, usr::A<int> const&)'
collect2: error: ld returned 1 exit status
The following version doesn't not work either:
#include <iostream>
namespace usr {
template <typename T>
class A {
public:
friend std::ostream& operator<<(std::ostream& os, const usr::A& a) {
os << "test";
return os;
}
};
}
int main() {
usr::A<int> a;
std::cout << a << std::endl;
return 0;
}
Here's the error I get plus a whole lot more which I'm not going to include here:
test2.cpp:8:55: error: invalid use of template-name ‘usr::A’ without an argument list
const usr::A& a) {
You need to take ostream in your function by reference. Also, when you declare a friend you need to include the template argument: friend std::ostream& operator<< <T>. Here's your first version modified that works for me:
#include <iostream>
namespace usr {
// Forward declarations
template <typename T> class A;
template <typename T>
std::ostream& operator<<(std::ostream& os, const usr::A<T>&);
// Class
template <typename T>
class A {
public:
friend std::ostream& operator<< <T>(std::ostream& os, const usr::A<T>& a);
};
// Friend function
template <typename T>
std::ostream& operator<<(std::ostream& os, const usr::A<T>& a) {
os << "test";
return os;
}
}
int main() {
usr::A<int> a;
std::cout << a << std::endl;
return 0;
}
The first answer to your referred to question would seem to answer this.
In the first case, you need the friend delcaration to declare a friend template rather than non-template overloaded functions:
friend std::ostream& operator<< <>(std::ostream &os, const usr::A<T>& a);
note the extra <> that designates this as a firend template.
In the second case, you need to prived the template argument to the friend function:
friend std::ostream& operator<<(std::ostream &os, const usr::A<T>& a) {
note the extra <T>, the type parameter to A
I am trying to overload the ostream operator in template and inherited classes and I have been following some tips here and here, but I get a redefinition error. Here is a reproduction of my code:
#include <iostream>
enum type
{
A,
B
};
template <type T>
class base
{
protected:
virtual std::ostream& print(std::ostream& out) const =0;
};
template <type T>
class derived: public base<T>
{
protected:
virtual std::ostream& print(std::ostream& out) const
{
out<<"Hello World.\n";
return out;
}
public:
template <type S>
friend std::ostream& operator<<(std::ostream& out, const derived<S>& D)
{
return (D.print(out));
}
};
int main ()
{
#ifdef __NOT_WORKING__
derived<A> a;
std::cout<<a;
derived<B> b;
std::cout<<b;
#else
derived<A> a;
std::cout<<a;
#endif
return 0;
}
If I define just a derived A class, everything works, but if I define a derived A and a derived B class I get this error from the compiler:
test.cpp: In instantiation of 'class derived<(type)1u>':
test.cpp:38:20: required from here
test.cpp:27:30: error: redefinition of 'template<type S> std::ostream& operator<<(std::ostream&, const derived<S>&)'
friend std::ostream& operator<<(std::ostream& out, const derived<S>& D)
^
test.cpp:27:30: note: 'template<type S> std::ostream& operator<<(std::ostream&, const derived<S>&)' previously defined here
test.cpp: In instantiation of 'std::ostream& operator<<(std::ostream&, const derived<S>&) [with type S = (type)1u; type T = (type)0u; std::ostream = std::basic_ostream<char>]':
test.cpp:39:20: required from here
test.cpp:20:31: error: 'std::ostream& derived<T>::print(std::ostream&) const [with type T = (type)1u; std::ostream = std::basic_ostream<char>]' is protected
virtual std::ostream& print(std::ostream& out) const
^
test.cpp:29:37: error: within this context
return (D.print(out));
^
Why is it redefining the friend function?
Thanks for your time.
PS. I am using gcc49.
Replace
template <type S>
friend std::ostream& operator<<(std::ostream& out, const derived<S>& D)
{
return (D.print(out));
}
with
friend std::ostream& operator<<(std::ostream& out, const derived<T>& D)
{
return (D.print(out));
}
error will go away.
With earlier definition, you are trying to define a new template function with same signature.
[temp.friend]/4:
When a function is defined in a friend function declaration in a class
template, the function is instantiated when the function is odr-used.
The same restrictions on multiple declarations and definitions that
apply to non-template function declarations and definitions also apply
to these implicit definitions.
Clang compiles the above fine - that can be considered a bug, but recall that violations of the ODR are ill-formed with no diagnostic required.
You have two ways to solve this. Extract the definition of the template:
template <typename T>
class derived: public base<T>
{
// [..]
template <type S>
friend std::ostream& operator<<(std::ostream& out, const derived<S>& D);
};
template <type S>
std::ostream& operator<<(std::ostream& out, const derived<S>& D)
{
return (D.print(out));
}
Or make the operator a non-template:
template <type T>
class derived: public base<T>
{
// [..]
friend std::ostream& operator<<(std::ostream& out, const derived<T>& D)
{
return (D.print(out));
}
};
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.
From what I know about friend functions this should work. I'm not sure what's going on.
In my code i define a class
template < class IType = unsigned int >
class BitArray {
...
friend ostream& operator<<(ostream&, const BitArray&);
friend istream& operator>>(istream&, BitArray&);
...
}
then later in the same header file
template < class IType >
ostream& operator<<(ostream& os, const BitArray<IType>& that)
{
...
}
template < class IType >
istream& operator>>(istream& is, BitArray<IType>& that)
{
...
}
and it's giving me
error LNK2019: unresolved external symbol
when I try to compile.
I've re-read and re-written this half a dozen times, and reviewed the use of the "friend" keyword, and can't find what's wrong.
does this implementation follow different rules because of the template
I also overwrote << and >> as shift operators, but again that shouldn't matter since they have different arguments;
With warning up, you have:
warning: friend declaration 'std::ostream& operator<<(std::ostream&, const BitArray<IType>&)' declares a non-template function [-Wnon-template-friend]
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
So declare the template function before:
template <class IType> class BitArray;
template <class IType> std::ostream& operator<<(std::ostream&, const BitArray<IType>&);
template <class IType> std::istream& operator>>(std::istream&, BitArray<IType>&);
template < class IType = unsigned int >
class BitArray {
friend std::ostream& operator<< <>(std::ostream&, const BitArray&);
friend std::istream& operator>> <>(std::istream&, BitArray&);
};
template <class IType>
std::ostream& operator<<(std::ostream& os, const BitArray<IType>& b)
{
/* Your implementation */
}
Live example
I think you want this:
template < class IType = unsigned int >
class BitArray {
template<class> friend ostream& operator<<(ostream&, const BitArray&);
template<class> friend istream& operator>>(istream&, BitArray&);
};
Your BitArray declaration is telling the compiler to look for a non-templated operator<< and operator>>
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.