Errors trying to overload template class friend << operator - c++

Trying to code a better version of array type i have run into an issue. For some reason the declaration doesnt work. It throws at me bunch of weird errors. Tried looking up the issue but havent found anything so far. Here is the code:
Template <class T>
class SafeArray {
private:
int size;
int elements;
int index;
T* arr;
public:
SafeArray(int n);
~SafeArray();
void push_back(T item);
void resize(int size);
friend std::ostream& operator << (std::ostream& os, const SafeArray<T>& ar)
};
And the implementation outside the class:
template<class T>
std::ostream& operator << <T> (std::ostream& os, const SafeArray<T> & arr) {
for (int i = 0; i < arr.elements; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
return os;
}

If you want friend template, the friend declaration should be
template <class T>
class SafeArray {
...
template<class X>
friend std::ostream& operator << (std::ostream& os, const SafeArray<X>& ar);
};
the implementation should be
template<class T>
std::ostream& operator << (std::ostream& os, const SafeArray<T> & arr) {
...
}
LIVE
BTW: In the implementation of operator<<, I think std::cout << arr[i] << " "; should be std::cout << arr.arr[i] << " ";.

Related

Wierd stuff happens when overloading operator<< with a class template

Here's the functionality I am expecting to achieve:
darray<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
std::cout << a << std::endl; // displays: {1, 2, 3}
My implementation:
template <typename T>
class darray
{
private:
long m_capacity;
long m_size;
T* m_data;
void resize();
public:
// constructors & destructors
darray();
// operations
void push_back(T);
std::ostream& print(std::ostream&) const;
template<typename U> friend std::ostream& operator<<(std::ostream& os, U const& ar);
};
template<typename T>
std::ostream& darray<T>::print(std::ostream& os) const
{
os << "{ ";
for (size_t i = 0; i < m_size; i++)
{
os << m_data[i] << ", ";
if ( i == m_size - 1 )
os << m_data[i];
}
os << " }\n";
return arr;
}
template<typename U>
std::ostream& operator<<(std::ostream& os, U const& obj)
{
return obj.print(os);
}
produces an error:
error: ambiguous overload for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘const char [66]’)
But, when I change the parameter of operator<< to accept a darray<U> instead , it works fine:
template<typename U>
std::ostream& operator<<(std::ostream& os, darray<U> const& obj)
{
return obj.print(os);
}
What am I missing here?
Update:
I also tried doing this, changing the parameter to darray<U> type in the definition and the implementation, but it still produces the same error:
template <typename T>
class darray
{
private:
long m_capacity;
long m_size;
T* m_data;
void resize();
public:
// constructors & destructors
darray();
// operations
void push_back(T);
std::ostream& print(std::ostream&) const;
template<typename U> friend std::ostream& operator<<(std::ostream& os, darray<U> const& ar);
};
template<typename T>
std::ostream& darray<T>::print(std::ostream& os) const
{
os << "{ ";
for (size_t i = 0; i < m_size; i++)
{
os << m_data[i] << ", ";
if ( i == m_size - 1 )
os << m_data[i];
}
os << " }\n";
return os;
}
template<typename U>
std::ostream& operator<<(std::ostream& os, darray<U> const& obj)
{
return obj.print(os);
}
Friend functions in template classes have to be defined inside the class declaration. This is the only way I have found to have the friend function to correctly accept an instance of the templated class with the expected template.
So here I would write:
...
friend std::ostream& operator<<(std::ostream& os, darray<T> const& ar) {
ar.print(os);
return os;
}
...
But beware: your class contains a raw pointer to allocated memory which is probably deleted in the class destructor. Per the rule of five, you must explicitely declare (or delete) the copy/move constructors and assignment operators.
In your darray<T>::print function, if you change
os << m_data[i] << ", ";
to
os << m_data[i];
os << ", ";
then the compiler doesn't complain and it works fine. I don't know why.

How to override output operator (<<) as a function template outside a class template

I am reading Section 2.4 of the book "C++ tempalte, a complete guide".
I tried to override output operator (<<) as a function template outside the class template Stack<>.
Below is my code, but it doesn't work.
#include <iostream>
#include <string>
#include <vector>
template<class T>
class Stack
{
private:
std::vector<T> v;
public:
void push(T a);
void printOn(std::ostream & os) const;
template <typename U>
friend std::ostream& operator<< (std::ostream& out, const Stack<U> & s);
};
template<typename T>
std::ostream& operator<< (std::ostream out, const Stack<T> & s)
{
s.printOn(out);
return out;
}
template<class T>
void Stack<T>::push(T a)
{
v.push_back(a);
}
template<class T>
void Stack<T>::printOn(std::ostream & out) const
{
for(T const & vi : v)
{out << vi << " ";}
}
int main()
{
Stack<int> s1;
s1.push(12);
s1.push(34);
std::cout << s1;
}
You are just omitting the &, which makes the operator<< inside and outside the class have different function signatures, they are both valid for std::cout << s1, hence the ambiguity
template<typename T>
std::ostream& operator<< (std::ostream& out, const Stack<T> & s)
// ^
{
s.printOn(out);
return out;
}

How to implement a << interface in C++?

I'm working on a tiny compiler, and I use boost::variant<bool, ClassA> infoto store the information of each node.
boost::variant will automatically call the correct << operator of a specific type when I call std::cout<< node.info;
However, since the built-in formatting function of ostream doesn't satisfy my requirement(print #t instead of 1 if node.info==true and print "string" instead of string), new types of bool/string should be introduced.
I want to implement a template class Wrapper<T>, which behaves just like T(because there are lots of old code) and provides the interface of <<.
At first, the following version was implemented:
template<typename T> class Wrapper : public T
{
public:
template<typename ... U> Wrapper(const U& ... a):T(a...) {}
friend std::ostream& operator <<(std::ostream& o, const Wrapper<T>& w);
};
This version works well for std::string, but when T=bool, since built-in types cannot be inherited, an error will raise.
My current workaround is to use partial specialization:
template<typename T, bool ISCLASS= std::is_class<T>::value> class Wrapper;
template<typename T> class Wrapper<T, false>
{
private:
T inner;
public:
template<typename ... U> Wrapper(const U& ... a): inner(a...) {}
//Wrap the operators (= + += ...)
template<typename U> Wrapper<T> operator !() { Wrapper<T> res(*this); res.inner=!res.inner; return res; }
operator T() const{ return inner; }
friend std::ostream& operator <<(std::ostream& o, const Wrapper<T>& w);
};
template<typename T> class Wrapper<T, true> : public T
{
public:
template<typename ... U> Wrapper(const U& ... a):T(a...) {}
friend std::ostream& operator <<(std::ostream& o, const Wrapper<T>& w);
};
Obviously it is not a perfect solution because I have to wrap every operators of bool or any other built-in types.
Any help would be appreciated.
Thanks.
Could we consider something simpler?
Create a simple wrapper, using reference or pointer.
template <class T>
struct MyFormattingWrapper
{
const T& nucleus;
};
And then a factory function for it.
template <class T>
MyFormattingWrapper<T> my_formatting(const T& n)
{
return MyFormattingWrapper<T>{ n };
}
And then, you can specialize the formatting for each type.
std::ostream& operator << (std::ostream& o, const MyFormattingWrapper<int>& w)
{
return o << "int:" << w.nucleus;
}
std::ostream& operator << (std::ostream& o, const MyFormattingWrapper<std::string>& w)
{
return o << "std::string:" << w.nucleus;
}
int main()
{
std::cout << my_formatting(123) << std::endl;
std::cout << my_formatting(std::string{ "abc" }) << std::endl;
}
Update:
C-string may be a special case. But it is not difficult.
struct MyFormattingWrapper_c_string
{
const char* const nucleus;
};
MyFormattingWrapper_c_string my_formatting(const char* n)
{
return MyFormattingWrapper_c_string{ n };
}
MyFormattingWrapper_c_string my_formatting(char* n)
{
return MyFormattingWrapper_c_string{ n };
}
std::ostream& operator << (std::ostream& o, const MyFormattingWrapper_c_string& w)
{
return o << "c-string:" << w.nucleus;
}
Nicky C's answer is great, but has an issue with partial specialization of functions not being OK. This means you can't produce a version that works on general vectors like this:
template<typename T>
std::ostream& operator << (std::ostream& o, const MyFormattingWrapper<std::vector<T>>& vec)
{
o << "vec:[ "
for(auto v : vec) {
o<<my_formatting(v);
o<<" ";
}
return o<<"]"
}
You can get around this by putting the core of the specialized output into the MyFormattingWrapper classes and having only one operator<<
// The default one
template <class T> struct MyFormattingWrapper {
const T& nucleus;
ostream& output(ostream & os) {
return os<<nucleus;
}
};
// Specialized for string
template <> struct MyFormattingWrapper<std::string> {
const std::string& nucleus;
ostream& output(ostream & os) {
return os<<"string:"<<nucleus;
}
};
// Specialized for vector
template <class T> struct MyFormattingWrapper<std::vector<T>> {
const std::vector<T>& nucleus;
ostream& output(ostream & os) {
os<<"vec:[";
for(auto & v: nucleus) {
os<<my_formatting(v)<<" ";
}
return os<<"]";
}
};
// Now there's just one of these, so partial template
// specialization doesn't cause us any problems
template<typename T>
std::ostream& operator << (std::ostream& os, const MyFormattingWrapper<T>& w) {
return w.output(os);
}
Perhaps I better make the follow-up regarding boost::variant another answer.
Firstly, learning from #MichaelAnderson, and considering the interoperability with boost::variant, I would like to improve the design of the wrapper. We add a constructor to enable type conversion for from the nucleus type to the wrapper type.
template <class T>
class MyFormatting;
template <class T>
MyFormatting<T> my_formatting(const T& n)
{
return MyFormatting <T>{n};
}
// int
template <>
class MyFormatting<int>
{
private:
const int& nucleus;
public:
MyFormatting(const int& n) : nucleus(n) {}
friend std::ostream& operator << (std::ostream& os, const MyFormatting& w)
{
return os << "int:" << w.nucleus;
}
};
// std::string
template <>
class MyFormatting<std::string>
{
private:
const std::string& nucleus;
public:
MyFormatting(const std::string& n) : nucleus(n) {}
friend std::ostream& operator << (std::ostream& os, const MyFormatting& w)
{
return os << "std::string:" << w.nucleus;
}
};
// c-string
template <>
class MyFormatting<char*>
{
private:
const char* nucleus;
public:
MyFormatting(const char* n) : nucleus(n) {}
friend std::ostream& operator << (std::ostream& os, const MyFormatting& w)
{
return os << "c-string:" << w.nucleus;
}
};
MyFormatting<char*> my_formatting(const char* n)
{
return MyFormatting<char*>{n};
}
// std::vector
template <class T>
class MyFormatting<std::vector<T>>
{
private:
const std::vector<T>& nucleus;
public:
MyFormatting(const std::vector<T>& n) : nucleus(n) {}
friend std::ostream& operator << (std::ostream& os, const MyFormatting& w)
{
os << "std::vector:[";
for (const auto& x : w.nucleus)
{
os << x << " ";
}
os << "]";
return os;
}
};
Next, let's use the wrapper with boost::variant. The constructor of the wrapper enables conversion between variant of nuclues types to variant of the wrappers.
boost::variant<int, std::string> var_int = 50;
boost::variant<int, std::string> var_str = "fifty";
boost::variant<MyFormatting<int>, MyFormatting<std::string>> var_fmt_int = var_int;
boost::variant<MyFormatting<int>, MyFormatting<std::string>> var_fmt_str = var_str;
std::cout << var_int << " " << var_str << std::endl;
std::cout << var_fmt_int << " " << var_fmt_str << std::endl;
But boost::variant<MyFormatting<int>, MyFormatting<std::string>> spells too long. We can make it shorter.
template <class... T>
using Variant_Formatting_t = boost::variant < MyFormatting<T>... > ;
std::cout << Variant_Formatting_t<int, std::string>{var_int} << " " << Variant_Formatting_t<int, std::string>{var_str} << std::endl;
Since boost::variant use macro-template metaprogramming to emulate variadic template instead of using C++11 variadic template, I cannot make it cleaner using type deduction. This is the furthest I can get to.

friend function for template class : C++

I have written a code:
#include <iostream>
#include <cassert>
using namespace std;
template<typename T>
class dynArray{
int size;
T* ptr;
public:
dynArray(int n=0);
~dynArray();
T& operator[] (const int index);
friend ostream& operator<<<T>(ostream& os,const dynArray<T>& A);
};
template<typename T> dynArray<T>::dynArray(int n):size(n){
if (size==0)
{
cout << "Size Zero"<< endl;
ptr=NULL;}
else
{
try{
ptr = new T[size];
cout << "Constructor Called" << endl;
}
catch(bad_alloc xa)
{
cout << "Allocation Failure" <<endl;
exit(EXIT_FAILURE);
}
}
}
template<typename T> dynArray<T>::~dynArray(){
cout << "Destructor Called for array of size : " << size << endl;
delete[] ptr;
}
template<typename T> T& dynArray<T>::operator[] (const int index){
assert(index >=0 && index <size);
return *(ptr+index);
}
template<typename T> ostream& operator<< <T>(ostream& os,const dynArray<T>& A){
for (int i=0; i < A.size ; i++)
os << *(A.ptr+i) << " ";
return os;
}
int main()
{
dynArray<int> array1;
dynArray<int> array2(5);
array2[0]=15;
array2[3]= 45;
cout << array2 << endl;
return 0;
}
But while compiling getting error:
$ g++ -Wall DynArray.cpp -o DynArray
DynArray.cpp:46: error: partial specialization `operator<< <T>' of function template
DynArray.cpp: In instantiation of `dynArray<int>':
DynArray.cpp:54: instantiated from here
DynArray.cpp:14: error: template-id `operator<< <int>' for `std::basic_ostream<char, std::char_traits<char> >& operator<<(std::basic_ostream<char, std::char_traits<char> >&, const dynArray<int>&)' does not match any template declaration
DynArray.cpp: In function `std::ostream& operator<<(std::ostream&, const dynArray<T>&) [with T = int]':
DynArray.cpp:61: instantiated from here
DynArray.cpp:8: error: `int dynArray<int>::size' is private
DynArray.cpp:47: error: within this context
DynArray.cpp:9: error: `int*dynArray<int>::ptr' is private
DynArray.cpp:48: error: within this context
I think my template syntax is wrong for operator<<. Can any one help please? Not able to figure out where is the mistake.
You cannot friend a specialization of an undeclared template function. You need to declare the operator << beforehand. Of course to do so, you'll need to already have a declaration of dynArray. This mess of forward declarations looks like this (Live at Coliru):
template<typename T> class dynArray;
template<typename T>
ostream& operator << (ostream& os, const dynArray<T>& A);
template<typename T>
class dynArray {
// ...
friend ostream& operator<< <T>(ostream& os, const dynArray& A);
};
As #ooga points out in his comment, the template parameters in the friend declaration are unnecessary; the compiler can deduce them. You could simply declare it as:
friend ostream& operator<< <> (ostream& os, const dynArray& A);
I personally find that syntax a bit punctuation-heavy in this instance.
Alternatively, if you find the forward declarations offensive, you could declare a separate non-template friend function for each specialization of dynArray by defining it in the class definition (Coliru again):
template<typename T>
class dynArray {
// ...
friend ostream& operator<< (ostream& os,const dynArray& A) {
for (int i=0; i < A.size ; i++)
os << *(A.ptr+i) << " ";
return os;
}
};
In the class declare friend as :-
template<typename U>
friend ostream& operator<<(ostream& os,const dynArray<U>& A);
And define it as :-
template<typename U>
ostream& operator<< (ostream& os,const dynArray<U>& A){...}
See HERE

using nested-types of a template-class as template parameter

I want to implement a template function using nested-types of a template-class.
I have just read here that it is better to implement operator << as non-member and non-friend function. Therefore I decided to move functions toStream() and tableToStream() outside MyClass:
template <typename T>
class MyClass
{
public:
typedef boost::dynamic_bitset<> BoolTable;
typedef std::vector<T> MsgTable;
private:
BoolTable b_;
MsgTable m_;
public:
const BoolTable& getB() const { return b_; }
const MsgTable & getM() const { return m_; }
std::ostream& toStream (std::ostream& os) const
{
os <<"Bool: "; tableToStream (os, getB()); os <<'\n';
os <<"Msg:"; tableToStream (os, getM()); os <<'\n';
return os;
}
template <typename TABLE>
std::ostream& tableToStream (std::ostream& os, const TABLE& table) const
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
};
template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T> mc)
{
return mc.toStream(os);
}
It's easy to convert MyClass::toStream() into an operator << non-member and non-friend function:
template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T>& mc)
{
os <<"Bool: "; mc.tableToStream (os, mc.getB()); os <<'\n';
os <<"Msg:"; mc.tableToStream (os, mc.getM()); os <<'\n';
return os;
}
But I want to use solely operator << instead of calling MyClass::tableToStream():
template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T>& mc)
{
os <<"Bool: "<< mc.getB() <<'\n';
os <<"Msg:" << mc.getM() <<'\n';
return os;
}
For the function MyClass::tableToStream() I could use the following implementation, but this may mess the stream output because the function is too generic (any type can be TABLE).
template <typename TABLE>
std::ostream& operator << (std::ostream& os, const TABLE& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
Therefore, I want to restrict to the nested types of MyClass. Below is one of my attempts to convert MyClass::tableToStream() into a standard operator << non-member and non-friend function:
template <typename T, typename MyClass<T>::TABLE>
std::ostream& operator << (std::ostream& os, const TABLE& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
But the error is about typename MyClass<T>::TABLE.
Since you have clarified your question a lot, my first answer does not apply any more and I'll remove-edit it to give you something that might fit better:
Updated answer:
You want to constrain the template to accept only types that are typedeffed inside your MyClass template. Such constraints are usually achieved by application of SFINAE, especially by std::enable_if (or boost::enable_if, if your library lacks that part of C++11 support). Sadly, there is no traits like a is_typedeffed_inside that could be used for your case. It's even worse: there is no way to write such a trait just using the plain typedefs, since there is nothing special about being typedeffed inside a given class - the compiler has no way to determine (and is not interested in) if a given known type has some alias name for it somewhere.
But if your typedefs are just the ones you show in your question, I have good news for you: you need exactly two operator<< for that:
One for boost::dynamic_bitset<>, since that is the BoolTable for any MyClass instantiation.
Another one, templated, for std::vector<T>, since that is the MsgTable for each corresponding MyClass<T>.
The downside is, that with this templated operator<<, you'd be able to output any std::vector<FooBar>, even if FooBar is completely unrelated to any use of MyClass. But that holds for any other possible implementation of the proper operator<<'s - if there's no explicit restriction on the MSG parameter, there's no restriction on a FooBar making a std::vector<FooBar> a viable MyClass<MSG>::MsgTable.
My conclusion for your question: you wanted to have the operator<< for its convenient looks, since it is normally used for thet purpose. In your case, you can provide it for MyClass<MSG> objects, but there is no way to do so for the inner typedefs alone.
I'd implement it that way:
template <class MSG>
class MyClass {
/* ... */
public:
// instead of declaring op<< a friend, redirect to a method that has
// natural access to private members
std::ostream& printToStream(std::ostream& os) const
{
os << "Bool: ";
tableToStream (getB(), os);
os <<"\nMsg:";
tableToStream (getM(), os);
return os <<'\n';
}
private:
// make this one private so nobody can misuse it to print unrelated stuff
template <class Table>
static void tableToStream(Table const& table, std::ostream& os)
{
std::copy(begin(table), end(table), ostream_iterator(os, ", "));
}
};
template <typename MSG>
std::ostream& operator << (std::ostream& os, const MyClass<MSG>& mc)
{
return mc.printToStream(os);
}
Your original class is fine. It is true that if you want to have an operator << for writing to a stream that it should be a non-member non-friend function, like you have, but there is no reason that function can't call a public member function to do the work.
I finally found this similar question
In my case the solution is:
template <typename T>
std::ostream& operator << (std::ostream& os,
typename MyClass<T>::TABLE const& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
UPDATE: As #ArneMertz pointed out, the above function does not work.
Below is the complete code I have tested:
#include <ostream>
#include <boost/dynamic_bitset.hpp>
template <typename T>
class MyClass
{
public:
typedef boost::dynamic_bitset<> BoolTable;
typedef std::vector<T> MsgTable;
BoolTable b_;
MsgTable m_;
const BoolTable& getB() const { return b_; }
const MsgTable & getM() const { return m_; }
};
template <typename T>
std::ostream& operator << (std::ostream& os,
typename MyClass<T>::TABLE const& table)
{
for (int i=0; i < table.size(); ++i)
os << table[i] <<',';
return os;
}
template <typename T>
std::ostream& operator << (std::ostream& os, const MyClass<T>& mc)
{
os <<"Bool: "<< mc.getB() <<'\n'; // <-- this line is OK because it
os <<"Msg: "<< mc.getM() <<'\n'; //uses boost operator<<
return os;
}
and the main function:
#include <iostream>
int main()
{
MyClass<int> var;
var.b_.push_back(true);
var.b_.push_back(false);
var.b_.push_back(true);
var.m_.push_back(23);
var.m_.push_back(24);
var.m_.push_back(25);
std::cout << var;
}
I believe you are confusing something. The typename is just to be able to seperate it from the other template-parameters. Try to rename it to
template <typename OS, typename MSG, typename MSGTable>
OS& operator << (OS& os, const MSGTable& table) const{}
and then use it like an object.
See here.