Overloading operator<< for endl using templates - c++

I have a class which inherits from ofstream. I want to overload the insertion operator so that it can be a drop in repalcement for ofstream.
The first overload is
template<class T>
MyClass& Myclass::operator<<(const T& in);
and to try and handle the manipulators like std::endl
template<
template<class, class> class Outer,
class Inner1,
class Inner2
>
MyClass& Myclass::operator<<(Outer<Inner1, Inner2>& (*foo)(Outer<Inner1, Inner2>&));
If I try to compile with:
Myclass output; output << 3 << "Hi";
Then everything works fine, but when I try to add std::endl
Myclass output; output << 3 << "Hi" << std::endl;
temp.cpp: In function 'int main()':
temp.cpp:10: error: no match for 'operator<<' in '((Stream*)ss. Stream::operator<< [with T = int](((const int&)((const int*)(&3)))))->Stream::operator<< [with T = char [3]](((const char (&)[3])"Hi")) << std::endl'
/usr/include/c++/4.1.2/bits/ostream.tcc:657: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.1.2/bits/ostream.tcc:597: note: std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, _CharT) [with _CharT = char, _Traits = std::char_traits<char>]
I especially don't understand why in the error printout there is a const int*.
This is also an attempt to learn some more about templates, but I am also trying to cover more manipulators with a single piece of code.
EDIT SSCCE:
#include <fstream>
#include <iostream>
class Myclass : public std::ofstream {
//class Stream {
private:
public:
template<class T>
Myclass& operator<<(const T& data_in) {
std::cout << data_in;
return *this;
}
template<
template<class, class> class Outer_T,
class Inner_T1,
class Inner_T2
>
Myclass& operator<<(Outer_T<Inner_T1, Inner_T2>& (*foo)(Outer_T<Inner_T1, Inner_T2>&)) {
return foo(*this);
}
};
int main() {
Myclass output;
output << 3 << "Hi";
output << 3 << "Hi" << std::endl;
}

Don't try it. The overloading of operator<< and operator>> for iostream types is complicated and messy.
What you should usually do instead is create your own std::streambuf subclass, and arrange for a standard stream class to use that. This way you can override what happens with the character stream data, without worrying about the overloaded operators, type conversion, formatting, and manipulators. For example, see James Kanze's Filtering Streambufs article, or the Boost library boost::iostreams.

Related

error overloading operator '>>'

I am trying to overload the >> operator, check my code, it's the most reduced program:
#include <iostream>
#include <string>
using namespace std;
class MyClass{
private:
string bar;
int foo;
public:
MyClass(){
bar="";
foo=0;
};
istream& operator>>(istream& is){
is >> bar >> foo;
return is;
};
ostream& operator<<(ostream& os){
os << bar << foo;
return os;
};
~MyClass(){};
};
int main()
{
MyClass* a = new MyClass();
cin >> *a;
delete a;
return 0;
}
This code doesn't compile, I've googled before post my question and I found the trouble could be the most vexing parse, but i cannot imagine how to fix it.
Anyway, I don't know where is the problem, when i try to compile, the compiler throws:
First:
error: no match for ‘operator>>’ (operand types are ‘std::istream {aka std::basic_istream<char>}’ and ‘MyClass’)
cin >> *a;
~~~~^~~~~
Then, after trying to convert the types to int, double, char, etc it throws:
/usr/include/c++/6.1.1/istream:924:5: nota: candidate:
std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&&, _Tp&) [con _CharT = char; _Traits = std::char_traits<char>; _Tp = MyClass] <coincidencia cercana>
operator>>(basic_istream<_CharT, _Traits>&& __is, _Tp& __x)
^~~~~~~~
/usr/include/c++/6.1.1/istream:924:5: nota: conversion of argument 1 would be ill-formed:
error: no se puede unir el l-valor ‘std::istream {aka std::basic_istream<char>}’ a ‘std::basic_istream<char>&&’
cin >> *a;
What can I do to solve this issue?
Overloading the input and output operators can't be done as member functions. The reason is that when you defined the >> or << operators as member functions the object instance of the class must be on the left hand side of the operator.
Instead define the operator functions as non-member friend functions (which can be done inline in the class) like
class MyClass
{
public:
...
friend std::ostream& operator<<(std::ostream& os, MyClass const& object)
{
return os << object.bar << object.foo;
}
};
">>" and "<<" operators are usually not implemented as member functions because the first argument is an implicit object of that class in a member function but you can do that and it will work if you would do something like *a >> cin in your main.Other wise implement these operators as global functions as explained in the above answer.

defining numeric_limits max function for template class

I have problem with defining function max for template class. In this class we kept a numbers not as simple integers, but as vector of numbers in some numeral system. And with defining numeric_limits i need to return representation of maximal number founded on a defined number system.
And i get many errors, when i'm trying to return class with maximal representation, but it works when returns integer.
My template class:
template<int n,typename b_type=unsigned int,typename l_type=unsigned long long,long_type base=bases(DEC)>
class NSizeN
{
public:
int a_size = 0;
vector <b_type> place_number_vector; // number stored in the vector
NSizeN(int a){ //constructor
do {
place_number_vector.push_back(a % base);
a /= base;
a_size ++;
} while(a != 0);
}
void output(ostream& out, NSizeN& y)
{
for(int i=a_size - 1;i >= 0;i--)
{
cout << (l_type)place_number_vector[i] << ":";
}
}
friend ostream &operator<<(ostream& out, NSizeN& y)
{
y.output(out, y);
return out << endl;
}
}
At the end of .h file i have this :
namespace std{
template<int n,typename b_type,typename l_type,long_type base>
class numeric_limits < NSizeN< n, b_type, l_type, base> >{
public :
static NSizeN< n, b_type, l_type, base> max(){
NSizeN< n, b_type, l_type, base> c(base -1);
return c;
}
}
I've tried this with const, with constexpr, and it doesn't work. I've no idea how to get rid of this errors :
error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to'std::basic_ostream<char>&&'
std::cout << std::numeric_limits<NSizeN<3> >::max() << endl;
error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = NSizeN<3>]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
And this is what i'm trying do in main:
std::cout << std::numeric_limits<NSizeN<3> >::max() << endl;
This is my assignment so don't judge the way of doing this, because it's my teacher choice and I hope I presented my problem fairly comprehensive.
The problem that you are facing is that you try to bind a temporary returned by your max() function to a non-const reference for the output operator.
The cleanest solution would be to declare the output operator as:
friend ostream &operator<<(ostream& out, const NSizeN& y)
and your output function as
void output(ostream& out) const
Note, that I also removed the unused second parameter for the output function. The const reference can be bound to both l-values and r-values, so it will work for the temporary returned by the max() function as well.
Edit
As #n.m. pointed out, you also don't use the stream that is actually passed to the operator << and just use the std::cout. The proper way to implement it is to simply use the stream (in your case just replace the cout << ... with out << ... in your output function. This will let statements such as std::cerr << std::numeric_limits<NSizeN<3> >::max(); work as intended.

Printing a non type template inner class

I have a non type class template (e.g. Counted) that points to an instance of a class template (e.g. Counter). Everything works fine as long as both template classes are siblings, for example writing a print operator.
Now for several reasons, I want to move Counted inside of Counter as an inner class, and I find myself unable to write a printing operator.
Here's a working "sibling class" version, with the main code here:
template < class Count >
struct Counter {
using count_type = Count;
count_type instances = 0;
};
template < class Cnt, Cnt& c>
struct Counted {
using id_type = typename Cnt::count_type;
id_type id;
Counted() : id(c.instances) { ++c.instances; }
~Counted() { --c.instances; }
};
template < class Cnt, Cnt& c >
std::ostream& operator<<(std::ostream& os, Counted<Cnt,c> sib) {
os << "printing sibling " << sib.id;
return os;
}
using SCounter = Counter<std::size_t>;
SCounter sc;
using SCounted = Counted<SCounter, sc>;
Here's the not compiling "inner class" version with the main code here :
template < class Count >
struct Counter {
using count_type = Count;
count_type instances = 0;
template <Counter& c>
struct Counted {
using id_type = count_type;
id_type id;
Counted() : id(c.instances) { ++c.instances; }
~Counted() { --c.instances; }
};
};
template < class Count, Counter<Count>& c >
std::ostream& operator<<(std::ostream& os,
typename Counter<Count>::template Counted<c>& sib) {
os << "printing inner " << sib.id;
return os;
}
using SCounter = Counter<std::size_t>;
SCounter sc;
using SCounted = SCounter::Counted<sc>;
Errors:
prog.cpp: In function 'int main()':
prog.cpp:32:15: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
std::cout << j << std::endl;
^
In file included from /usr/include/c++/4.9/iostream:39:0,
from prog.cpp:1:
/usr/include/c++/4.9/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Counter<unsigned int>::Counted<(* & sc)>]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
Is there a problem in my code, in my compiler, or is this simply not allowed by the standard ?
Koenig operators are what you want:
template <Counter& c>
struct Counted {
using id_type = count_type;
id_type id;
Counted() : id(c.instances) { ++c.instances; }
~Counted() { --c.instances; }
friend std::ostream& operator<<(
std::ostream& os,
Counted const& sib
) {
os << "printing inner " << sib.id;
return os;
}
};
};
here we create a friend operator<<. It will be found via ADL (or Koenig lookup) when you try to use << with a Counted instance.
A different function is created, and no template deduction is done, for each type of Counted.

How to use enable_if to conditionally define a << operator

I'm trying to define a << operator for a set of classes; the set is open, but all of the members have a common tagging base class, and all have the member function std::string String() const. Basically, what I've got is:
class Tag {};
class Obj : public Tag
{
public:
std::string String() const { return "specialized"; }
};
template <typename T>
typename std::enable_if<std::is_base_of<Tag, T>::type, std::ostream>::value& operator<<( std::ostream& dest, T const& source)
{
dest << source.String();
return dest;
}
int
main()
{
std::cout << typeid(std::enable_if<std::is_base_of<Tag, Obj>::value, std::ostream>::type).name() << std::endl;
std::string s( "generic" );
Obj e;
std::cout << e << std::endl;
std::cout << s << std::endl;
return 0;
}
This doesn't work: with g++ (version 4.8.3, invoked with -std=c++11), I get the error message:
enableIf.cc: In function 'int main()':
enableIf.cc:55:18: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
std::cout << e << std::endl;
^
In file included from /usr/lib/gcc/x86_64-pc-cygwin/4.8.3/include/c++/iostream:39:0,
from enableIf.cc:8:
/usr/lib/gcc/x86_64-pc-cygwin/4.8.3/include/c++/ostream:602:5: error: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Obj]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
I can't figure it out, because there aren't any rvalue-references in sight; the compiler seems to have struck on the generic overload for std::ostream&& in the standard library.
With MSC (VS 2013), the error message is a lot more verbose, but it starts with:
enableIf.cc(55) : error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'Obj' (or there is no acceptable conversion)
and then goes on to list a lot of possible functions, all in the standard library.
(In my actual code, line 55 corresponds to the line std::cout << e << std::endl;.)
In both cases, the compiler seems to be rejecting my overloaded function. If I comment out the << lines, however, the code compiles, and the value output by the first line in main seems correct (at least with MSC—the output of g++ is So, what ever that's supposed to mean).
Given that two compilers agree, I assume that there is an error in my code, but I can't figure out what. How do you do this? (FWIW: I'd be equally happy, or even happier, with a solution which generates the overload for all types having a member function std::string Type::String() const.)
I'm pretty sure you meant this:
template <typename T> // here here
typename std::enable_if<std::is_base_of<Tag, T>::type, std::ostream>::value&
operator<<( std::ostream& dest, T const& source)
to be this:
template <typename T>
typename std::enable_if<std::is_base_of<Tag, T>::value, std::ostream>::type&
operator<<( std::ostream& dest, T const& source)
after changing as such, you compile successfully.

Why does outputting a class with a conversion operator not work for std::string?

This works, printing 1:
#include <iostream>
struct Int {
int i;
operator int() const noexcept {return i;}
};
int main() {
Int i;
i.i = 1;
std::cout << i;
}
However, this fails to compile on GCC 4.8.1:
#include <iostream>
#include <string>
struct String {
std::string s;
operator std::string() const {return s;}
};
int main() {
String s;
s.s = "hi";
std::cout << s;
}
Here are the relevant parts of the error:
error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream}’ and ‘String’)
std::cout << s;
snip
template std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&)
operator<<(basic_ostream<_CharT, _Traits>& __os,
/usr/include/c++/4.8/bits/basic_string.h:2753:5: note: template argument deduction/substitution failed:
main.cpp:25:18: note: ‘String’ is not derived from ‘const std::basic_string<_CharT, _Traits, _Alloc>’
std::cout << s;
I only use std::cout and std::string, which have the same template arguments. I'm really not sure why this wouldn't be able to pick up the implicit conversion like it did for Int. Why does it work with int, but not std::string?
That operator is a free template function. User defined conversions do not get checked when matching against a template function arguments, it instead uses type pattern matching (substitution).
In theory a SFINAE overload using std::is_convertable<> would be able to do what you want, but that technique was not used when operator<< that outputs a std::string to a basic_ostream<char> was defined.
A manual overload to output your class to basic_ostream<...> will fix your problem.
I would do this:
struct String {
std::string s;
operator std::string() const {return s;}
friend std::ostream& operator<<( std::ostream& os, String const& self) {
return os<<self.s;
}
};
which has the added benefit of not creating a wasted copy.
The << operator seems to have a pool of overloads with types other than std::string.
as I have seen by using the clang++ compiler.
The compiler does the implicit conversion from String to std::string but it does not match any of the defined << operators.
If you define the << operator for std::string it will work
#include <iostream>
#include <string>
std::ostream& operator<<(std::ostream& s, const std::string& str)
{
s << str.c_str();
return s;
}
struct String {
std::string s;
operator std::string() const {return s;}
};
int main() {
String s;
s.s = "hi";
std::cout << s;
}
You can find more details on the same issue here: http://forums.codeguru.com/showthread.php?432227-RESOLVED-Implicit-conversion-to-std-string
As seen in one post;
The problem is the operator<< here is a template and no template instantiations can be made for the type TestClass since the user defined conversions are probably not being considered in argument deduction for templates for implicit instantiations (atleast I could not find in section 14.7.1 (Implicit instantiation). This results in an empty overload set for the call "std::cout << obj << '\n';" and hence the error. It does not matter if an instantiation already happened or not. Template candidates are chosen into overload set on exact matches (except for array to pointer decay and const qualification - http://groups.google.co.in/group/com...29910b6?hl=en&).
When you provide an explicit overload operator<< with type std::string, it is non-template and adds up in the overload set and hence invoking the implicit conversion while doing overload resolution/a callable match.