I'm trying to overload operator<<, and it drove me crazy:
std::ostream& operator<<(std::ostream & lhs, TuringMachine::TRTable& rhs){
for(auto& statePtr : rhs){
lhs << statePtr.first->getLabel().toStdString();
for(auto& charPtr: statePtr.second){
//lhs << '\t';
lhs << charPtr.first.toAscii() ;
//lhs << 'b ';
lhs << charPtr.second.getState().getLabel().toStdString() << std::endl;
}
}
return lhs;
}
TRTable is a typedeffor std::map<State*, std::multimap<QChar, Transition>>. Statehas its label as a QString hence the call to .toStdString().
In another class I call std::cout << machine->table << std::endl; with machine beeing a TuringMachine* and this gives me
error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
What am I doing wrong? Why &&?
EDIT: using g++ 4.6 and -std=c++0x
In which namespace did you declare the operator<<? Since TRTable is a typedef ADL does not apply, so the operator<< is searched only in namespace std by ADL, since this is where the actual class is defined. So you might have to use the namespace where you defined the operator<< when you want to use it.
lhs should have type std::ostream &. No const.
rhs should be const TuringMachine::TRTable&:
std::ostream& operator<<(std::ostream& lhs, const TuringMachine::TRTable& rhs)
Related
I run into a compiler error when an inner class uses the template parameter of the outer class, and I instantiate an output stream operator on the outer class on the member of the inner type.
I have spent a good bit of time trying to resolve this problem. I believe the following sources come close but I still do not understand why I am getting a compilation failure.
https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types
https://msdn.microsoft.com/en-us/library/71dw8xzh.aspx
Here is the code:
#include <iostream>
#include <vector>
template <typename T>
struct Outer
{
struct Inner
{
Inner(const T& val = T());
T data_;
}; // end class Inner
Outer();
void AddInnerChildToOuter(const T& data);
std::vector<typename Outer<T>::Inner> innerChildren_;
}; // end class Outer
// Inner constructor
template <typename T>
Outer<T>::Inner::Inner(const T& val) : data_(val)
{
}
template <typename T>
std::ostream& operator<<(std::ostream& strm, // Line 27
const typename Outer<T>::Inner& gn)
{
strm << gn.data_ << std::endl;
return strm;
}
// Outer constructor
template <typename T>
Outer<T>::Outer()
{
}
template <typename T>
void Outer<T>::AddInnerChildToOuter(const T& data)
{
typename Outer<T>::Inner node(data);
innerChildren_.push_back(node);
}
template <typename T>
std::ostream& operator<<(std::ostream& strm, const Outer<T>& g)
{
for (size_t i = 0; i < g.innerChildren_.size(); ++i)
std::cout << g.innerChildren_[i] << std::endl; // Line 51
return strm;
}
int main()
{
Outer<int> g;
g.AddInnerChildToOuter(3);
g.AddInnerChildToOuter(5);
std::cout << g << std::endl; // Line 60
return 0;
}
I get a compiler error for the ostream operator << on the outer that calls the corresponding output stream operator for the inner. I am not posting the entire litany of the compiler's error messages; just what I consider to be relevant.
$ g++ -Wall -W -Wextra -pedantic -ansi OuterInnerArgh.cpp
OuterInnerArgh.cpp: In instantiation of ‘std::ostream& operator<<(std::ostream&, const Outer<T>&) [with T = int; std::ostream = std::basic_ostream<char>]’:
OuterInnerArgh.cpp:60:18: required from here
OuterInnerArgh.cpp:51:19: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘const Outer<int>::Inner’)
std::cout << g.innerChildren_[i] << std::endl;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
(snipped compiler's attempts at various ostream overloads; more compiler error messages below)
OuterInnerArgh.cpp:27:15: note: candidate: template<class T> std::ostream& operator<<(std::ostream&, const typename Outer<T>::Inner&)
std::ostream& operator<<(std::ostream& strm,
^~~~~~~~
OuterInnerArgh.cpp:27:15: note: template argument deduction/substitution failed:
OuterInnerArgh.cpp:51:19: note: couldn't deduce template parameter ‘T’
std::cout << g.innerChildren_[i] << std::endl;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
OuterInnerArgh.cpp:48:15: note: candidate: template<class T> std::ostream& operator<<(std::ostream&, const Outer<T>&)
std::ostream& operator<<(std::ostream& strm, const Outer<T>& g)
^~~~~~~~
OuterInnerArgh.cpp:48:15: note: template argument deduction/substitution failed:
OuterInnerArgh.cpp:51:19: note: ‘const Outer<int>::Inner’ is not derived from ‘const Outer<T>’
std::cout << g.innerChildren_[i] << std::endl;
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
(snipped rest of compiler errors)
Please let me know why I encounter a compiler error -
Even though I have an ostream operator << for typename Outer<T>::Inner&
Even when I have "sprinkled" the typename "magic-dust" wherever relevant
Only for the outer ostream operator, not for the constructors or the inner ostream operator (the latter probably not instantiated at all?)
Why does the compiler say ‘const Outer<int>::Inner’ is not derived from ‘const Outer<T>’? (Yes, there is no inheritance, but the inner type definition is nested within the outer)
You got compile error because non-deduced context causes template argument deduction failing.
In the following cases, the types, templates, and non-type values that are used to compose P do not participate in template argument deduction, but instead use the template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
The nested-name-specifier (everything to the left of the scope resolution operator ::) of a type that was specified using a qualified-id:
For example, if you specify the template argument explicitly (in ugly style) it would compile. In the operator<< for Outer:
operator<< <T> (strm, g.innerChildren_[i]);
// ^^^
You can make the operator<< non-template (to bypass the type deduction trouble), then you have to define it inside the class definition as friend. e.g.
struct Inner
{
Inner(const T& val = T());
T data_;
friend std::ostream& operator<<(std::ostream& strm,
const Inner& gn)
{
strm << gn.data_ << std::endl;
return strm;
}
};
LIVE
Fix this
std::cout << g.innerChildren_[i] << std::endl; // Line 51
to be
std::cout << g.innerChildren_[i].data_ << std::endl; // Line 51
Because you are trying to use the operator << where it is not defined
If you depend on the defined operator in line (27), modify line (50) to call it properly, as follows
for (size_t i = 0; i < g.innerChildren_.size(); ++i)
{
operator<< <T>(strm, g.innerChildren_[i]);
strm << std::endl;
}
This question already has answers here:
Calling a function overloaded in several namespaces from inside one namespace
(3 answers)
Closed 4 years ago.
Using gcc version 5.2.0 (GCC) with --std=c++14, the following code does not compile anymore, if the commented out operator ostream in namespace MyNamespace is uncommented. Is this a bug or a feature? (Compile with g++ -c --std=c++14 x.cxx)
#include <string>
#include <iostream>
typedef std::pair<std::string, std::string> StringPair;
std::ostream& operator<<( std::ostream&, const StringPair &pair) {
std::cout <<pair.first<<"."<<pair.second;
}
namespace MyNamespace {
class MyClass {};
//std::ostream& operator<< (std::ostream&, const MyClass &);
void xxx ();
}
void MyNamespace::xxx () {
StringPair pair;pair.first="1";pair.second="2";
std::cout <<pair<<std::endl;
}
The error-message i get with the operator << uncommented is:
x.cxx: In function ‘void MyNamespace::xxx()’:
x.cxx:18:13: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘StringPair {aka std::pair<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >}’)
std::cout <<pair<<std::endl;
^
As stated here, this is an example of name hiding. By defining operator<< in namespace MyNamespace all the definitions from the higher namespaces (like global) are hidden.
Note that as stated here:
[...]this feature doesn't interfere with Koenig lookup [...], so IO operators from std:: will still be found.
(details about Koenig lookup)
The solution is to refer to the overload in the other namespace with the using directive, as described here and here. This was mentioned in the comments by Michael Nastenko.
Thus using ::operator<<;, with :: referring to the global namespace.
Thus the code will become:
#include <string>
#include <iostream>
typedef std::pair<std::string, std::string> StringPair;
std::ostream& operator<<(std::ostream& os, const StringPair &pair) {
os << pair.first << '.' << pair.second;
return os;
}
namespace MyNamespace {
class MyClass {};
using ::operator<<;
std::ostream& operator<< (std::ostream&, const MyClass &);
void xxx();
}
void MyNamespace::xxx() {
StringPair pair("1","2");
std::cout<<pair<<std::endl;
}
int main() {
MyNamespace::xxx();
return 0;
}
example on Coliru
I am testing a template:
template<typename Key>
struct _Tarray<Key, char>{
map<const Key, string> data;
//stuff
operator bool(){cout << " just testing"; return false;} //trying to call this, but its not answering
};
So, I am driving it like this:
_Tarray<int, char> out;
cout << out;
Here is my overloaded operator<<:
template<typename T, typename U>
ostream& operator<< (ostream& os, const _Tarray<T, U>& var){
//now i expect operator bool() to be called here
if(var){os << " Yes !";} //and bool is not being called. my compiler (g++) is angry
else{cout << " No !";}
return os;
}
Which gives me
./template.h: In instantiation of 'std::ostream& operator<<(std::ostream&, const _Tarray<T, U>&) [with T = int; U = char; std::ostream = std::basic_ostream<char>]':
./template.h:128:41: required from 'void var_dump(const T&) [with T = _Tarray<int, char>]'
functions.cpp:12:21: required from here
./template.h:122:5: error: passing 'const _Tarray<int, char>' as 'this' argument discards qualifiers [-fpermissive]
if(var){os << "heheheheh";}
^
./template.h:73:5: note: in call to '_Tarray<Key, char>::operator bool() [with Key = int]'
Why is it giving me a compiler error and what can I do to fix it?
var is a const _Tarray<T, U>&. The important information here is that it is const, which means, that no function can be called from var if they modify the properties of var.
The compiler doesn't know that your operator bool doesn't modify anything, so it fails. You have to explicitly state that your operator bool won't modify _Tarray, by specifying the function as const:
//Note the 'const', operator bool own't change anything, so the call from a const
//instance is legal
operator bool() const
{
std::cout << "Just testing\n";
return false;
}
In your operator<< var is const. Since it is const you can only call const qualified member functions. Since your operator bool is not marked as const you cannot use it. To fix it change operator bool to
operator bool() const {cout << " just testing"; return false;}
I am trying to save an STL map containing custom objects to a file, using fstream. I am doing this using << and >> operator overloading.
#include <iostream>
#include <string>
#include <map>
#include <fstream>
#define DELIM '/'
struct Point{
public:
int x, y;
};
//operator overloads for point
std::istream& operator>>(std::istream& is, Point& p){
std::string input;
std::getline(is, input, DELIM);
p.x = std::stoi(input);
std::getline(is, input, DELIM);
p.y = std::stoi(input);
return is;
}
std::ostream& operator<<(std::ostream& os, Point& p){
os << p.x << DELIM << p.y << DELIM;
return os;
}
//operator overloads for map<string, point>
std::istream& operator>>(std::istream& is, std::map<std::string, Point>& m){
std::string input;
std::getline(is, input, DELIM);
int map_size = std::stoi(input);
for(int i = 0; i < map_size; i++){
std::getline(is, input, DELIM);
Point p; is >> p;
m[input] = p;
}
return is;
}
std::ostream& operator<<(std::ostream& os, std::map<std::string, Point>& m){
os << m.size() << DELIM;
for(const auto& pair : m){
os << pair.first << DELIM;
os << pair.second;
}
return os;
}
int main(){
Point p1;
p1.x = 1; p1.y = 2;
Point p2;
p2.x = 100; p2.y = 150;
std::map<std::string, Point> map;
map["p1"] = p1;
map["p2"] = p2;
return 0;
}
When I try to compile this file I get the following error:
test.cpp: In function 'std::ostream& operator<<(std::ostream&, std::map<std::basic_string<char>, Point>&)':
test.cpp:44:14: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
os << pair.second;
Any idea how to fix this? I ran into this problem earlier with templates, however there are no templates used here. Other answers on SO also involved templates and did not help me. An explanation of why this is happening would be appreciated too!
The command I used to compile: (MinGW, gcc 4.8.1)
g++ test.cpp -o test -std=c++11 -Wall
The full error message:
test.cpp: In function 'std::ostream& operator<<(std::ostream&, std::map<std::basic_string<char>, Point>&)':
test.cpp:44:14: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
os << pair.second;
^
In file included from c:\mingw\lib\gcc\x86_64-w64-mingw32\4.8.1\include\c++\iostream:39:0,
from test.cpp:1:
c:\mingw\lib\gcc\x86_64-w64-mingw32\4.8.1\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 = Point]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
Thank you!!
Here
for(const auto& pair : m){
os << pair.first << DELIM;
os << pair.second;
}
pair is const, so pair.second will be const Point too, which can't match the parameter type Point& of operator<<.
Change the parameter type of Point for operator<< to const reference:
std::ostream& operator<<(std::ostream& os, const Point& p){
~~~~~
os << p.x << DELIM << p.y << DELIM;
return os;
}
Mostly, the argument passed to operator<< is not expected to be changed, so it's good practice to declare the type to const& for both operator<<.
std::ostream& operator<<(std::ostream& os, const Point& p){
std::ostream& operator<<(std::ostream& os, const std::map<std::string, Point>& m){
The argument passed to the overloaded << operator should be a constant reference, not a mutable reference.
I am creating a class SpyOutput that mimics cout, and I am trying to use a template so I don't have to overload the << operator 4 times (one for each data type):
#include <iostream>
#include <sstream>
using namespace std;
class SpyOutput
{
ostream *os;
stringstream ss;
int sum, temp;
public:
SpyOutput(ostream *s):os(s), sum(0){}
template <class T>
SpyOutput& operator<<(T x)
{
ss << x;
*os << x;
return *this;
}
};
int main(void)
{
SpyOutput spy(&cout);
spy << "Hello" << endl;
spy << "1235" << endl;
spy << 'z' << endl;
spy << 4.56 << endl;
return 0;
}
I can't get it to compile, it doesn't seem to recognize my template. Any ideas? The G++ error message is
main.cpp: In function 'int main()':
main.cpp:24:20: error: no match for 'operator<<' (operand types are 'SpyOutput' and '<unresolved overloaded function type>')
spy << "Hello" << endl;
^
main.cpp:24:20: note: candidates are:
main.cpp:13:16: note: template<class T> SpyOutput& SpyOutput::operator<<(T)
SpyOutput& operator<<(T x)
^
main.cpp:13:16: note: template argument deduction/substitution failed:
main.cpp:24:23: note: couldn't deduce template parameter 'T'
spy << "Hello" << endl;
^
The key part of the error message is "template argument deduction/substitution failed". endl is not an object, it's not even a function. It is a function template, which is a "cookie cutter" used to generate an infinite number of cookie-functions. When << to a ostream, the the compiler sees if any of the potential << functions can clarify what the template arguments should be. And there exists this overload:
ostream& operator<< (ostream& (*pf)(ostream&));
When the compiler checks this overload, it realizes that it can unambiguously specialize endl as a ostream& (*)(ostream&), and so selects this overload and does the implicit specialization matching the stream's type. Luckily, all you have to do is also provide the above function overload, and hopefully this magic will work for you as well.
As a note, ostreams have two other important overloads as members you'll have to add as well:
ostream& operator<< (ios& (*pf)(ios&));
ostream& operator<< (ios_base& (*pf)(ios_base&));
It's also worth mentioning that your function is attempting to make copies of all objects you stream, which can cause it to fail or act wierd. A more sane idea is to use a universal reference. Or at least capture by const reference.
//if T is a template, then T&& is a universal reference. A perfect match for everything
//if T were not a template, it would be an rvalue reference. Totally unrelated.
template <class T> SpyOutput& operator<<(T&& x) {
ss << x;
*os << x;
return *this;
}
Your code fails simply because std::endl is a function template, and therefore the compiler needs to know which instantiation of the template you want to use. The standard IOStream classes have separate overloads for manipulators, and they explicitly specify the template instantiation. You can do that as well:
SpyOutput& operator<<(std::ostream& (*manip)(std::ostream&))
{
if (os) manip(*os);
return *this;
}
Now when you do spy << std::endl this will instantiate std::endl<char, std::char_traits<char>> which is valid, and the code will work. Though in general I wouldn't recreate an entire stream class but rather use the std::streambuf interface.