error overloading operator '>>' - c++

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.

Related

cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’

There have been a couple posts on this subject, but I think this is one of the simplest examples, and hopefully it will clarify some things about cout and initialization.
So this works:
class A {
public:
std::ostream& operator<< (std::ostream& os) {
return os;
}
};
class B {
std::ostream& operator<< (std::ostream& os) {
A a(); // <-- LOOK
std::cout << a;
return os;
}
};
But if I simply A a() to A a:
class A {
public:
std::ostream& operator<< (std::ostream& os) {
return os;
}
};
class B {
std::ostream& operator<< (std::ostream& os) {
A a; // <-- LOOK
std::cout << a;
return os;
}
};
It throws:
nvcc main.cpp util.cpp -o main -lcublas -std=c++11
In file included from main.cpp:9:0:
cout-test.hpp: In member function ‘std::ostream& B::operator<<(std::ostream&)’:
cout-test.hpp:21:20: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
std::cout << a;
^
In file included from /usr/include/c++/4.8/iostream:39:0,
from main.cpp:5:
/usr/include/c++/4.8/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 = A]’
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
make: *** [main] Error 1
I get the same error if I make A a a class member:
class B {
A a; // <-- LOOK
std::ostream& operator<< (std::ostream& os) {
std::cout << a;
return os;
}
};
What gives?
First Case
A a();
does not construct an object. It declares a function. This parsing problem is known as The Most Vexing Parse.
A a();
std::cout << a;
works because a is converted to a bool in this case. See Why does pointer to int convert to void* but pointer to function convert to bool? why that works.
Second Case
A a;
std::cout << a;
does not work because of the way you have defined the operator<< function. You'll have to use
A a;
a << std::cout;
The operator<< function needs to be a non-member function in order to use:
A a;
std::cout << a;
See my answer to another SO post to understand why.

"no match" and "cannot bind lvalue" errors while overloading `operator<<` with `std::wostream` and `std::string`

I've got an error while overloading std::wostream::operator<<() for std::string.
Here is the minimal test case illustrating my problem:
#include <string>
#include <sstream>
inline std::wostream &operator<<(std::wostream &os, const std::string &)
{
return os;
}
class FakeOstream{};
namespace mynamespace {
class FakeClasse1 {
friend inline FakeOstream &operator<<(FakeOstream &out, const FakeClasse1 &) {
return out;
}
};
class FakeClasse2 {
friend inline FakeOstream &operator<<(FakeOstream &out, const FakeClasse2 &) {
return out;
}
};
void test()
{
auto mystring = std::string{u8"mystring"};
std::wostringstream s;
s << mystring; // The errors occur here
}
} // namespace mynamespace
The code can be compiled and executed here: http://cpp.sh/9emtv
As you can see here, there is an overload for operator<< with std::wostream
and std::string. The two fake classes are empty apart from the declaration of
an operator<< with FakeOstream and themselves. The test() function
instantiate an std::wostringstream and feed it a std::string. The fake
fake classes and test function are in a namespace.
This code yields the following error on cpp.sh at the line s << mystring;:
In function 'void mynamespace::test()':
25:10: error: cannot bind 'std::basic_ostream<wchar_t>' lvalue to 'std::basic_ostream<wchar_t>&&'
In file included from /usr/include/c++/4.9/istream:39:0,
from /usr/include/c++/4.9/sstream:38,
from 2:
/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 = wchar_t; _Traits = std::char_traits<wchar_t>; _Tp = std::basic_string<char>]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
When using directly g++ (version 5.3.0 from MSYS2), a no match error is also
displayed:
./tmpbug.cpp: In function 'void mynamespace::test()':
./tmpbug.cpp:25:7: error: no match for 'operator<<' (operand types are 'std::wostringstream {aka std::__cxx11::basic_ostringstream<wchar_t>}' and 'std::__cxx11::basic_string<char>')
s << mystring;
^
In file included from C:/Appli/msys64/mingw64/include/c++/5.3.0/istream:39:0,
from C:/Appli/msys64/mingw64/include/c++/5.3.0/sstream:38,
from ./tmpbug.cpp:2:
C:/Appli/msys64/mingw64/include/c++/5.3.0/ostream:628:5: note: candidate: std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = wchar_t; _Traits = std::char_traits<wchar_t>; _Tp = std::__cxx11::basic_string<char>] <near match>
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
C:/Appli/msys64/mingw64/include/c++/5.3.0/ostream:628:5: note: conversion of argument 1 would be ill-formed:
./tmpbug.cpp:25:10: error: cannot bind 'std::basic_ostream<wchar_t>' lvalue to 'std::basic_ostream<wchar_t>&&'
s << mystring;
^
In file included from C:/Appli/msys64/mingw64/include/c++/5.3.0/istream:39:0,
from C:/Appli/msys64/mingw64/include/c++/5.3.0/sstream:38,
from ./tmpbug.cpp:2:
As far as I know, all the parts of the example are necessary for the errors to
appear. If I comment out the namespace, the fake classes or just one of the
operator<< in the fake classes, the code compile just fine. Moreover, if I
just move one of the fake classes or the test function outside of the namespace,
the code will also compile just fine.
Additionnally, I tried compiling this example on clang 3.7 by using the compiler
from http://cppreference.com, and the code seems to compile without problems.
Is there a problem with my code or is this a GCC bug ? If this is a GCC bug, is
there a workaround ?
This is a bad idea:
inline std::wostream &operator<<(std::wostream &os, const std::string &)
as you should not overload operators on two types in std that do not depend on your own (outside of std or build-in) types. Doing ... doesn't work well. And, in my opinion, shouldn't be allowed.
Regardless, you can generate the same problem with conforming code by simply creating your own namespace notstd and own type notstd::string, then in the global root namespace defining
inline std::wostream &operator<<(std::wostream &os, const notstd::string &)
{
return os;
}
and get the same symptoms. So that doesn't matter much.
Operators are found first via unqualified name lookup, then via argument dependent lookup.
As we have no using statement, unqualified name lookup first looks in the enclosing namespace. If nothing is found, the namespaces containing it (and eventually the file/global namespace) are then searched.
ADL then augments this with operators found via ADL or Koenig lookup -- it looks in the namespaces of the arguments and their template parameters.
Now, the friend operator<< you defined do live in the namespace their class contains, but they are usually difficult to find.
Somehow your double-declaration of friend operator<< is making your code find them, and stop looking into the global namespace for a <<.
To me this looks like a bug. Neither of those "Koenig operators" should be visible to bog-standard unqualified name lookup with types unrelated to the classes they are "contained" in.
MCVE:
#include <iostream>
#include <sstream>
namespace notstd {
struct string {};
}
inline void operator<<(std::wostream &os, const notstd::string &){ return; }
class FakeOstream{};
namespace mynamespace {
class UnusedClass1 {
friend inline void operator<<(FakeOstream &out, const UnusedClass1 &) { return; }
};
class UnusedClass2 {
// comment this line out and the code compiles:
friend inline void operator<<(FakeOstream &out, const UnusedClass2 &) { return; }
};
void test() {
auto mystring = notstd::string{};
std::wostringstream s;
s << mystring; // The errors occur here
}
} // namespace mynamespace
int main(){}
live example.
#T.C. found what appears to be this bug being fixed:
test code
fix in gcc

Overloading operator<< for endl using templates

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.

Error calling the overloaded istream operator in a Template Class

I want to overload the ">>" operator in a template class, but when I am trying to write someting into a vector I am getting some errors.
This is a part of my Vector function:
#include <iostream>
template<typename T>
class Vector
{
public:
T operator[](const int& i);
template <T> friend
std::ostream& operator<<(std::ostream& out, const Vector &v);
template <T> friend
std::istream& operator>>(std::istream& in, Vector<T> &v);
};
template<typename T>
std::istream& operator>>(std::istream& in, Vector<T> &v) {
for(int i =0; i < v.getSize(); i++) {
in >> v[i];
}
}
I used this test to write into a vector:
int main {
Vector<int> v1(5);
cin >> v1;
}
This is the error:
Vector.h: In function ‘std::istream& operator>>(std::istream&, Vector<T>&) [with T = int, std::istream = std::basic_istream<char>]’:
testVector.cpp:9:9: instantiated from here
Vector.h:94:3: error: ambiguous overload for ‘operator>>’ in ‘in >> (& v)->Vector<T>::operator[] [with T = int]((*(const int*)(& i)))’
Vector.h:94:3: note: candidates are:
/usr/include/c++/4.6/istream:122:7: note: std::basic_istream<_CharT, _Traits>::__istream_type& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>::__istream_type& (*)(std::basic_istream<_CharT, _Traits>::__istream_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_istream<_CharT,
This is a part of my code. If I am using in a test function only something like this, it compiles:
Vector<int> v1.
cout << v1.getSize();
Update:
I've modified the >> operator overloading definition like this:
template<typename T> std::istream& operator>>(std::istream& in, Vector<T> &v) {
T tmp;
for(int i =0; i < v.getSize(); i++) {
in >> tmp;
v[i] = tmp;
}
}
This is the definition of the operator[]:
template<typename T> T Vector<T>::operator[](const int& i) {
return elements[i];
}
I get this error:
Vector.h:96:3: error: lvalue required as left operand of assignment
How should I overwrite the >> operator?
Thanks.
These lines:
template <T> friend std::ostream& ...
template <T> friend std::istream& ...
The template argument should be a type. As you've written it, it takes an object of said type.
template<typename U> friend std::ostream& ...
template<typename U> friend std::istream& ...
And you didn't specify a template argument here:
Vector v1(5);
^
Your problem has nothing to do with stream overloading:
You have two constructors with the same argument int. The names of the constructor doesn't matter main thing is the type. So two Vector<T>(int) will give you error overloading error.
You do not have an overloaded subscript operator (operator[]), set it up to fix the main problem
as 0x499602D2 mentioned, change the friend classes to the correct form because you will get error "accessing private member variable of class Vector" if you tried to use private members. In your scenario, you are accessing public members, so you might not even need friending the stream overloading. Read about friend here. So, ask yourself a question? "Will the stream operator function access the private member of class Vector?" If yes, use friend; otherwise remove it from your class declaration.
Remove the def from the source code. We understand that its coming from a source file.
The test program doesn't work because you haven't specified which template parameter you are using.
EDIT: added link for (3) to read about friendship

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.