I define the operator<< for std::string objects:
std::string & operator<< (std::string & left, std::string & right){
return left += right;
}
Then I use it:
std::string t1("t1"), t2("t2"), t3;
t3 = t2 << t1;
And get from a compiler:
t.cpp: In function 'int main()':
t.cpp:44:28: error: no matching function for call to 'operator<<(std::string&, std::string&)'
t.cpp:44:28: note: candidates are:
In file included from d:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/iostream:40:0,
from connection.h:10,
from login.cpp:1:
d:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ostream:600:5: note: template<class _CharT, class _Traits, class _Tp> std::basic_ostream<_CharT
, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&)
d:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ostream:600:5: note: template argument deduction/substitution failed:
t.cpp:44:28: note: 'std::string {aka std::basic_string<char>}' is not derived from 'std::basic_ostream<_CharT, _Traits>'
In file included from d:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/iostream:40:0,
Why talks it about ostream and does not talk about string? I.e. why it does not take in account my definition of the operator<< ?
Thanks.
Update. For those who is able just to say "why do you create operator<< for strings?" and is not able to say any helpful things:
std::string & operator<< (std::string & left, const int num){
return left += std::to_string(num);
}
std::string t3;
t3 << 3 << 5;
std::cout << t3 << std::endl;
And log:
t.cpp: In function 'int main()':
t.cpp:45:12: error: no match for 'operator<<' in 't3 << 3'
t.cpp:45:12: note: candidates are:
In file included from d:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/iostream:40:0,
from connection.h:10,
from login.cpp:1:
d:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ostream:600:5: note: template<class _CharT, class _Traits, class _Tp> std::basic_ostream<_CharT
, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&)
d:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/c++/ostream:600:5: note: template argument deduction/substitution failed:
t.cpp:45:12: note: 'std::string {aka std::basic_string<char>}' is not derived from 'std::basic_ostream<_CharT, _Traits>'
It does work:
#include <iostream>
#include <string>
std::string & operator<< (std::string & left, std::string & right){
return left += right;
}
int main()
{
std::string t1("t1"), t2("t2"), t3;
t3 = t2 << t1;
std::cout << t3;
}
Output: t2t1 [GCC 4.8.1]
The compiler output, as you say yourself, indicates that your operator overload is not even visible. You must not have your declaration in the right place.
This is not really a good idea, anyway: you will simply confuse the heck out of anybody who reads your code. Strings are not streams.
Related
I’m using Visual Studio and I'm reacquainting myself with C++ before taking a few classes.
This is an old script that used to compile, but now istream is giving me a few syntax errors. If anyone can lead me in the right direction, that would be great.
Fraction.h
friend istream& operator >> (istream& in, const Fraction& f);
Fraction.cpp
istream& operator >> (istream& in, const Fraction& f) {
cout << "Enter numerator" << endl;
in >> f.num;// error line
cout << "Enter denominator" << endl;
in >> f.denom; // error line
return in;
}
Visual Studio Error Summary
Terminal Error Bottom Small Portion
/usr/include/c++/8/istream:803:5: note: template argument deduction/substitution failed:
/home/spamandsons/projects/laney/Fraction.cpp:188:13: note: cannot convert ‘f.Fraction::denom’ (type ‘const int’) to type ‘unsigned char*’
in >> f.denom;
~~^~~~~
In file included from /usr/include/c++/8/iostream:40,
from /home/spamandsons/projects/laney/Fraction.cpp:2:
/usr/include/c++/8/istream:808:5: note: candidate: ‘template<class _Traits> std::basic_istream<char, _Traits>& std::operator>>(std::basic_istream<char, _Traits>&, signed char*)’
operator>>(basic_istream<char, _Traits>& __in, signed char* __s)
^~~~~~~~
/usr/include/c++/8/istream:808:5: note: template argument deduction/substitution failed:
/home/spamandsons/projects/laney/Fraction.cpp:188:13: note: cannot convert ‘f.Fraction::denom’ (type ‘const int’) to type ‘signed char*’
in >> f.denom;
~~^~~~~
In file included from /usr/include/c++/8/iostream:40,
from /home/spamandsons/projects/laney/Fraction.cpp:2:
/usr/include/c++/8/istream:980:5: note: candidate: ‘template<class _Istream, class _Tp> typename std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >, std::__is_convertible_to_basic_istream<_Istream>, std::__is_extractable<typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type, _Tp&&, void> >::value, typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type>::type std::operator>>(_Istream&&, _Tp&&)’
operator>>(_Istream&& __is, _Tp&& __x)
^~~~~~~~
/usr/include/c++/8/istream:980:5: note: template argument deduction/substitution failed:
/usr/include/c++/8/istream: In substitution of ‘template<class _Istream, class _Tp> typename std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >, std::__is_convertible_to_basic_istream<_Istream>, std::__is_extractable<typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type, _Tp&&, void> >::value, typename std::__is_convertible_to_basic_istream<_Tp>::__istream_type>::type std::operator>>(_Istream&&, _Tp&&) [with _Istream = std::basic_istream<char>&; _Tp = const int&]’:
/home/spamandsons/projects/laney/Fraction.cpp:188:13: required from here
/usr/include/c++/8/istream:980:5: error: no type named ‘type’ in ‘struct std::enable_if<false, std::basic_istream<char>&>’
The terminal process terminated with exit code: -1.
Terminal will be reused by tasks, press any key to close it.
Because it takes reference to CONST type. const Fraction& f, it must not be (just remove "const" in the both declaration and definition), the stream input operator is about to modify this object. Instead, const should be used in the stream output operator (e.g. std::ostream& operator<<(std::ostream& os, const Fraction& f)), where outputted object is not supposed to be modified.
I am trying to use Strong Types and to add stream operator for them.
In my source file I put all of these helpers in an anonymous namespace. One of these helpers is using a template stream operator (utils::to_hex(T)) defined in another header.
namespace { // Anonymous namespace
// Example custom strong type
using custom_type = utils::StrongType<std::uint32_t, struct Custom>;
// Stream operator for custom type
std::ostream &operator<<(std::ostream &_os, const custom_type &_value)
{
return (_os << utils::to_hex(static_cast<std::uint32_t>(_value)));
}
}
int main(void)
{
custom_type c = 0xDEADBEEF;
std::cout << c << std::endl;
}
The whole code: http://cpp.sh/2ln7q
I cannot compile this code. I am stuck with:
test.cc: In function ‘std::ostream& {anonymous}::operator<<(std::ostream&, const custom_type&)’:
test.cc:72:14: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘utils::ToHex<unsigned int>’)
return (_os << utils::to_hex(static_cast<std::uint32_t>(_value)));
Using the cpp.sh compiler I got:
In function 'std::ostream& {anonymous}::operator<<(std::ostream&, const custom_type&)':
73:65: error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'
In file included from /usr/include/c++/4.9/istream:39:0,
from /usr/include/c++/4.9/sstream:38,
from /usr/include/c++/4.9/iomanip:45,
from 3:
/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 = utils::ToHex<unsigned int>]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
When I remove the anonymous namespace of if I use the static keyword everything is fine.
Am getting compilation errors for the following snippet of my C++ code.
struct Power{
int power;
int age;
int operator-(const Power& p1)
{
return this->power - p1.power;
}
};
int main() {
Power p1;
p1.power = 1;
p1.age = 25;
Power p2;
p2.power = 2;
p2.age = 26;
std::cout<<std::minus<Power>()(p1, p2)<<std::endl;
}
build with c++11. cannot be built.
error messages are:
error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘Power’)
std::cout<<std::minus<Power>()(p1, p2)<<std::endl;
^
In file included from /usr/include/c++/5/iostream:39:0,
from rvaluereference.cpp:1:
/usr/include/c++/5/ostream:628:5: note: candidate: std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = Power] <near match>
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
/usr/include/c++/5/ostream:628:5: note: conversion of argument 1 would be ill-formed:
rvaluereference.cpp:60:39: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
.....
std::minus has a single template parameter that defines the type of both inputs and the output; it doesn't handle type switching AFAICT. Your operator- takes Power, and returns int, but std::minus<Power> must take and return Power. The complaint is because std::minus<Power> returns Power, and ostream doesn't have an overload for operator<< that accepts Power.
As noted in the comments, if you can use C++14, std::minus<void> accepts mismatched arguments and deduces the return type, so if you can use C++14, that's another option.
While std::minus only can do T operator-(const T &lhs, const T &rhs), your operators do not have the same limitations. Declare the operator outside of the class:
int operator-(const Power &lhs, const Power &rhs) {
return lhs.power - rhs.power;
}
and now you can do std::cout << p1 - p2 << std::endl;
Solved the problem already when checking a last time before posting this, but it looked somewhat evil to debug (at least for a newbie), so I'll post it anyway - feel free to delete.
The problem was that in the marked line below, ofstream seemed unable to write a simple string; the templating appeared to be the problem:
template <typename T>
void appendVectorToCSV(const std::string& header, std::vector<T> row,
const std::string& outfilename){
std::ofstream fout(outfilename);
fout << header;// << ","; /* The error line 80 */
...
This gives the error:
varUtils.hpp: In function ‘void appendVectorToCSV(std::string&, const std::vector<_RealType>&, const string&)’:
varUtils.hpp:80:10: error: no match for ‘operator<<’ (operand types are ‘std::ofstream {aka std::basic_ofstream<char>}’ and ‘std::string {aka std::basic_string<char>}’)
fout << header;// << ",";
^
varUtils.hpp:80:10: note: candidates are:
...
/usr/include/c++/4.8/complex:524:5: note: template<class _Tp, class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::complex<_Tp>&)
operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x)
^
/usr/include/c++/4.8/complex:524:5: note: template argument deduction/substitution failed:
...
varUtils.hpp:80:13: note: ‘std::ofstream {aka std::basic_ofstream<char>}’ is not derived from ‘std::basic_ostream<_CharT, _Traits>’
fout << header;// << ",";
^
So, solution:
A missing header.
#include <iostream>
was already there, but not
#include <fstream>
i'm playing around with inheritance. I'm completely baffled by the compiler
error i'm getting and looking it up it seems completely unrelated to what i'm trying
to do which is simply initialize my class.
here are the errors:
In file included from main.cpp:2:0:
student.h: In constructor ‘Student::Student(std::string, int, std::string, double)’:
student.h:13:3: error: class ‘Student’ does not have any field named ‘gnu_dev_major’
student.h: In function ‘std::ostream& operator<<(std::ostream&, const Student&)’:
student.h:25:8: error: no match for ‘operator<<’ in ‘os << "Name\011: "’
student.h:25:8: note: candidates are:
student.h:24:16: note: std::ostream& operator<<(std::ostream&, const Student&)
student.h:24:16: note: no known conversion for argument 2 from ‘const char [8]’ to ‘const Student&’
/usr/include/c++/4.6/bits/basic_string.h:2693:5: note: template<class _CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&)
student.h:25:32: error: ‘endl’ is not a member of ‘std’
student.h:26:8: error: no match for ‘operator<<’ in ‘os << "Age\011: "’
student.h:26:8: note: candidates are:
student.h:24:16: note: std::ostream& operator<<(std::ostream&, const Student&)
student.h:24:16: note: no known conversion for argument 2 from ‘const char [7]’ to ‘const Student&’
/usr/include/c++/4.6/bits/basic_string.h:2693:5: note: template<class _CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&)
student.h:26:30: error: ‘endl’ is not a member of ‘std’
student.h:27:8: error: no match for ‘operator<<’ in ‘os << "Major\011: "’
student.h:27:8: note: candidates are:
student.h:24:16: note: std::ostream& operator<<(std::ostream&, const Student&)
student.h:24:16: note: no known conversion for argument 2 from ‘const char [9]’ to ‘const Student&’
/usr/include/c++/4.6/bits/basic_string.h:2693:5: note: template<class _CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&)
student.h:27:34: error: ‘endl’ is not a member of ‘std’
student.h:28:8: error: no match for ‘operator<<’ in ‘os << "GPA\011: "’
student.h:28:8: note: candidates are:
student.h:24:16: note: std::ostream& operator<<(std::ostream&, const Student&)
student.h:24:16: note: no known conversion for argument 2 from ‘const char [7]’ to ‘const Student&’
/usr/include/c++/4.6/bits/basic_string.h:2693:5: note: template<class _CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&)
student.h:28:30: error: ‘endl’ is not a member of ‘std’
main.cpp: In function ‘int main()’:
main.cpp:8:2: error: ‘cout’ was not declared in this scope
whats confusing me is the very first error i'm getting:
student.h: In constructor ‘Student::Student(std::string, int,
std::string, double)’: student.h:13:3: error: class ‘Student’ does not
have any field named ‘gnu_dev_major’
here is my code:
1 #ifndef STUDENT_H
2 #define STUDENT_H
3
4 #include <iostream>
5 #include <string>
6 #include "person.h"
7
8 class Student : public Person {
9 friend std::ostream & operator<<(std::ostream &,const Student &);
10 public:
11 Student(std::string name, int age, std::string m="undecided", double gpa=0.0) :
12 Person::Person(name,age),
13 major(m),
14 gpa(gpa)
15 {}
16
17
18
19 protected:
20 double gpa;
21 std::string major;
22 };
23
24 std::ostream & operator<<(std::ostream &os,const Student &s){
25 os << "Name\t: " << s.name << std::endl;
26 os << "Age\t: " << s.age << std::endl;
27 os << "Major\t: " << s.major << std::endl;
28 os << "GPA\t: " << s.gpa << std::endl;
29 }
30
31 #endif
also if anyone has a pointer as to what might be going wrong in my overloaded
operator << help with that is also appreciated =).
You need to declare your overloaded << operator as friend inside your class:
Inside your Student class declare it as follows:
class Student {
// rest of code
friend std::ostream & operator<<(std::ostream &os,const Student &s);
}