Unable to overload stream extraction operator (>>) in C++ - c++

I'm currently trying to understand the basic concepts of operator overloading in C++. Therefore, I created a class wheel that is able to read from a stream by overloading the stream extraction operator >>.
wheel.h
#ifndef WHEEL_H
#define WHEEL_H
#include <cassert>
#include <ostream>
#include <string>
class wheel final {
float rimDiameter;
int productionYear;
std::string velocityIndex = "N/A";
std::string manufacturer = "N/A";
public:
wheel() = default;
wheel( float rimDiameter,
int productionYear,
std::string velocityIndex,
std::string manufacturer
) : rimDiameter{rimDiameter},
productionYear{productionYear},
velocityIndex{velocityIndex},
manufacturer{manufacturer}
{}
~wheel() = default;
friend
auto operator<<(std::ostream &os, const wheel &self) -> std::ostream &;
friend
auto operator>>(std::istream &is, wheel &self) -> std::istream &;
};
#endif
wheel.cpp
#include "wheel.h"
auto operator<<(std::ostream &os, const wheel &self) -> std::ostream & {
return os << " WHEEL" << std::endl
<< " =============================" << std::endl
<< " Rim Diameter: " << self.rimDiameter << "\"" << std::endl
<< " Year of Production: " << self.productionYear << std::endl
<< " Velocity Index: " << self.velocityIndex << std::endl
<< " Manufacutrer: " << self.manufacturer << std::endl;
}
auto operator>>(std::istream &is, wheel &self) -> std::istream & {
char c[3];
is >>
self.rimDiameter >> c[0] >>
self.productionYear >> c[1] >>
self.velocityIndex >> c[2] >>
self.manufacturer;
assert(c[0] == ';' && c[1] == ';' && c[2] == ';');
return is;
}
main.cpp
#include <iostream>
#include "wheel.h"
int main(void) {
wheel w;
std::cin >> w;
std::cout << w;
return 0;
}
To me, it all looks fine, but somehow I keep getting an error telling me that there is no match for 'operator>>' (operand types are 'std::istream {aka std::basic_istream<char>}' and 'float'):
$ make
g++-7 -g -std=c++17 -Wall -Wextra -Wconversion -Wpedantic -c main.cpp
g++-7 -g -std=c++17 -Wall -Wextra -Wconversion -Wpedantic -c wheel.cpp
wheel.cpp: In function 'std::istream& operator>>(std::istream&, wheel&)':
wheel.cpp:16:8: error: no match for 'operator>>' (operand types are 'std::istream {aka std::basic_istream<char>}' and 'float')
is >>
~~~^~
self.rimDiameter >> c[0] >>
~~~~~~~~~~~~~~~~
wheel.cpp:13:6: note: candidate: std::istream& operator>>(std::istream&, wheel&)
auto operator>>(std::istream &is, wheel &self) -> std::istream & {
^~~~~~~~
wheel.cpp:13:6: note: no known conversion for argument 2 from 'float' to 'wheel&'
In file included from /usr/local/Cellar/gcc/7.2.0/include/c++/7.2.0/string:53:0,
from /usr/local/Cellar/gcc/7.2.0/include/c++/7.2.0/bits/locale_classes.h:40,
from /usr/local/Cellar/gcc/7.2.0/include/c++/7.2.0/bits/ios_base.h:41,
from /usr/local/Cellar/gcc/7.2.0/include/c++/7.2.0/ios:42,
from /usr/local/Cellar/gcc/7.2.0/include/c++/7.2.0/ostream:38,
from wheel.h:5,
from wheel.cpp:1:
/usr/local/Cellar/gcc/7.2.0/include/c++/7.2.0/bits/basic_string.tcc:1465:5: note: candidate: template<class _CharT, class _Traits, class _Alloc> std::basic_istream<_CharT, _Traits>& std::operator>>(std::basic_istream<_CharT, _Traits>&, std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&)
operator>>(basic_istream<_CharT, _Traits>& __in,
^~~~~~~~
/usr/local/Cellar/gcc/7.2.0/include/c++/7.2.0/bits/basic_string.tcc:1465:5: note: template argument deduction/substitution failed:
wheel.cpp:17:14: note: mismatched types 'std::__cxx11::basic_string<_CharT, _Traits, _Alloc>' and 'float'
self.rimDiameter >> c[0] >>
^~~~~~~~~~~
make: *** [wheel.o] Error 1
What am I missing here?

You need to include iostream for input and output like this #include <iostream> and you'll avoid the error.
When outputting, it's the class over which the << operators are defined you always use ostream, but you forgot the case of inputting for >>.
#ifndef WHEEL_H
#define WHEEL_H
#include <cassert>
#include <iostream>
#include <string>
class wheel final {
float rimDiameter;
int productionYear;
std::string velocityIndex = "N/A";
std::string manufacturer = "N/A";
public:
wheel() = default;
wheel( float rimDiameter,
int productionYear,
std::string velocityIndex,
std::string manufacturer
) : rimDiameter{rimDiameter},
productionYear{productionYear},
velocityIndex{velocityIndex},
manufacturer{manufacturer}
{}
~wheel() = default;
friend
auto operator<<(std::ostream &os, const wheel &self) -> std::ostream &;
friend
auto operator >> (std::istream &is, wheel &self) -> std::istream &;
};
#endif /* wheel_hpp */

As #Ext3h pointed out, I am missing the respective include for istream.
Adding #include <istream> to wheel.h resolves the problem.
Thank you very much for you help, would have taken me forever to figure out the issue!

Related

boost test fails to find custom print

For some reason boost::test can't manage to compile the following code
#define BOOST_TEST_MODULE EPUTests
#include <iostream>
#include <boost/test/unit_test.hpp>
using epu8 = uint8_t __attribute__((vector_size(16)));
std::ostream &operator<<(std::ostream &stream, epu8 const &term) {
stream << "[" << unsigned(term[0]);
for (unsigned i = 1; i < 16; ++i)
stream << "," << unsigned(term[i]);
stream << "]";
return stream;
}
bool failtest(epu8 x) { return false; }
//****************************************************************************//
BOOST_AUTO_TEST_SUITE(EPU8_test)
BOOST_AUTO_TEST_CASE(EPU8_equal) {
epu8 x {};
BOOST_CHECK_PREDICATE(failtest, (x));
}
BOOST_AUTO_TEST_SUITE_END()
//****************************************************************************//
The error message is
In file included from /usr/include/boost/test/tools/floating_point_comparison.hpp:21:0,
from /usr/include/boost/test/tools/old/impl.hpp:21,
from /usr/include/boost/test/test_tools.hpp:46,
from /usr/include/boost/test/unit_test.hpp:18,
from boost_test_epu.cpp:4:
/usr/include/boost/test/tools/detail/print_helper.hpp: In instantiation of 'struct boost::test_tools::tt_detail::print_log_value<__vector(16) unsigned char>':
/usr/include/boost/test/tools/detail/print_helper.hpp:178:5: required from 'std::ostream& boost::test_tools::tt_detail::operator<<(std::ostream&, const boost::test_tools::tt_detail::print_helper_t<T>&) [with T = __vector(16) unsigned char; std::ostream = std::basic_ostream<char>]'
/usr/include/boost/test/utils/lazy_ostream.hpp:66:29: required from 'std::ostream& boost::unit_test::lazy_ostream_impl<PrevType, T, StorageT>::operator()(std::ostream&) const [with PrevType = boost::unit_test::lazy_ostream; T = boost::test_tools::tt_detail::print_helper_t<__vector(16) unsigned char>; StorageT = const boost::test_tools::tt_detail::print_helper_t<__vector(16) unsigned char>&; std::ostream = std::basic_ostream<char>]'
boost_test_epu.cpp:29:1: required from here
/usr/include/boost/test/tools/detail/print_helper.hpp:47:5: error: static assertion failed: Type has to implement operator<< to be printable
BOOST_STATIC_ASSERT_MSG( (boost::has_left_shift<std::ostream,T>::value),
I understand that g++ is complaining that my epu8 type is not printable. However I know it is because changing
BOOST_CHECK_PREDICATE(failtest, (x));
by
std::cout << x << std::endl;
BOOST_CHECK(failtest(x));
works as expected and print by vector variable correctly.
The same error is reported with various version of clang++ and g++
What am I doing wrong ?
BOOST::test requires the console output operator<< to be in the std namespace
namespace std
{
ostream &operator<<(...)
...
}

How to create a custom channel in SystemC?

I am trying to create a custom channel in System C. Channel data structure is like following
struct Command {
int cmdType;
int lba;
double timestamp;
int size;
Command() { }
Command(const int c, const int l, const double ts, const int sz) {
make(c, l, ts, sz);
}
void make(const int c, const int l, const double ts, const int sz) {
cmdType = c;
lba = l;
timestamp = ts;
size = sz;
}
inline bool operator ==(const Command & command) const {
return (command.cmdType == cmdType && command.lba == lba
&& command.timestamp == timestamp
&& command.size == size); }
};
ostream and trace functions for this channel are defined as follows
inline ostream & operator <<(ostream & os, const Command command)
{
os << "CmdType " << command.cmdType << endl;
os << "Lba " << command.lba << endl;
os << "Time " << command.timestamp <<endl;
os << "Data " << command.size << endl;
return os;
}
inline void sc_trace(sc_trace_file * &tf, const Command & command, string &name)
{
sc_trace(tf, command.cmdType, name + ".cmdType");
sc_trace(tf, command.lba, name + ".lba");
sc_trace(tf, command.timestamp, name + ".timestamp");
sc_trace(tf, command.size, name + ".size");
}
however I am getting compile error
the error message is very long, however here is the last part
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:312:6: note: candidate expects 4 arguments, 3 provided
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:317:6: note: void sc_core::sc_trace(sc_core::sc_trace_file*, const sc_core::sc_signal_in_if<short int>&, const string&, int)
void sc_trace( sc_trace_file* tf,
^
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:317:6: note: candidate expects 4 arguments, 3 provided
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:322:6: note: void sc_core::sc_trace(sc_core::sc_trace_file*, const sc_core::sc_signal_in_if<int>&, const string&, int)
void sc_trace( sc_trace_file* tf,
^
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:322:6: note: candidate expects 4 arguments, 3 provided
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:327:6: note: void sc_core::sc_trace(sc_core::sc_trace_file*, const sc_core::sc_signal_in_if<long int>&, const string&, int)
void sc_trace( sc_trace_file* tf,
^
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:327:6: note: candidate expects 4 arguments, 3 provided
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:343:1: note: void sc_core::sc_trace(sc_core::sc_trace_file*, const unsigned int&, const string&, const char**)
sc_trace( sc_trace_file* tf,
^
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:343:1: note: candidate expects 4 arguments, 3 provided
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:351:13: note: void sc_core::sc_trace(sc_core::sc_trace_file*, const void*, const string&)
extern void sc_trace( sc_trace_file* tf,
^
/home/user/user/systemc-2.3.1//include/sysc/tracing/sc_trace.h:351:13: note: no known conversion for argument 2 from ‘const Command’ to ‘const void*’
In file included from /home/user/user/systemc-2.3.1//include/sysc/communication/sc_clock_ports.h:31:0,
from /home/user/user/systemc-2.3.1//include/systemc:79,
from /home/user/user/systemc-2.3.1//include/systemc.h:208,
from initiator.h:5,
from initiator.cpp:1:
/home/user/user/systemc-2.3.1//include/sysc/communication/sc_signal_ports.h:1808:1: note: template<class T> void sc_core::sc_trace(sc_core::sc_trace_file*, const sc_core::sc_inout<T>&, const string&)
sc_trace( sc_trace_file* tf, const sc_inout<T>& port,
^
/home/user/user/systemc-2.3.1//include/sysc/communication/sc_signal_ports.h:1808:1: note: template argument deduction/substitution failed:
/home/user/user/systemc-2.3.1//include/sysc/communication/sc_signal_ports.h:1165:46: note: ‘const Command’ is not derived from ‘const sc_core::sc_inout<T>’
sc_trace( p->tf, iface->read(), p->name );
^
/home/user/user/systemc-2.3.1//include/sysc/communication/sc_signal_ports.h:1791:1: note: template<class T> void sc_core::sc_trace(sc_core::sc_trace_file*, const sc_core::sc_in<T>&, const string&)
sc_trace(sc_trace_file* tf, const sc_in<T>& port, const std::string& name)
^
/home/user/user/systemc-2.3.1//include/sysc/communication/sc_signal_ports.h:1791:1: note: template argument deduction/substitution failed:
/home/user/user/systemc-2.3.1//include/sysc/communication/sc_signal_ports.h:1165:46: note: ‘const Command’ is not derived from ‘const sc_core::sc_in<T>’
sc_trace( p->tf, iface->read(), p->name );
^
appreciate help regarding how to fix this compile issue
here is simple version of the code --- file main.c
#include <stdio.h>
#include <csignal>
#include "systemc.h"
#include "producer.h"
#include "consumer.h"
#include "stdtype.h"
#include <iomanip>
#include <sstream>
using namespace std;
inline ostream & operator <<(ostream & os, const Command command)
{
os << "CmdType " << command.cmdType << endl;
return os;
}
inline void sc_trace(sc_trace_file * tf, const Command & command, const string & name)
{
int* cmdType = (int*) &(command.cmdType);
sc_trace(tf, cmdType, name + ".cmdType");
}
int sc_main(int arg_num, char *arg_vet[])
{
sc_clock clock("clock", 100, SC_PS);
sc_signal <bool> reset;
sc_signal <Command> cmd;
Producer *prd;
prd = new Producer("Producer");
prd->clock(clock);
prd->reset(reset);
prd->cmd_tx(cmd);
Consumer *con;
con = new Consumer("Consumer");
con->clock(clock);
con->reset(reset);
con->cmd_rx(cmd);
sc_trace_file *tf = NULL;
tf = sc_create_vcd_trace_file("trace");
sc_trace(tf, reset, "reset");
sc_trace(tf, clock, "clock");
reset.write(1);
sc_start(100, SC_NS);
reset.write(0);
sc_start(100, SC_NS);
sc_close_vcd_trace_file(tf);
return 0;
}
file consumer.h
#ifndef __CONSUMER_H__
#define __CONSUMER_H__
#include <queue>
#include <systemc.h>
#include "stdtype.h"
using namespace std;
SC_MODULE(Consumer)
{
sc_in_clk clock;
sc_in <bool> reset;
sc_in <Command> cmd_rx;
void ConsumerProcess();
SC_CTOR(Consumer) {
SC_METHOD(ConsumerProcess);
sensitive << reset;
sensitive << clock.pos();
}
};
#endif
file producer.h
#ifndef __PRODUCER_H__
#define __PRODUCER_H__
#include <queue>
#include <systemc.h>
#include "stdtype.h"
using namespace std;
SC_MODULE(Producer)
{
sc_in_clk clock;
sc_in <bool> reset;
sc_out <Command> cmd_tx;
void ProducerProcess();
SC_CTOR(Producer) {
SC_METHOD(ProducerProcess);
sensitive << reset;
sensitive << clock.pos();
}
};
#endif
file consumer.cpp
#include "consumer.h"
void Consumer:: ConsumerProcess(void)
{
cout << "con" << endl;
}
file producer.cpp
#include "producer.h"
void Producer:: ProducerProcess(void)
{
cout << "prd" << endl;
}
and file stdtype.h
#ifndef __STDTYPE_H__
#define __STDTYPE_H__
#include <queue>
#include <systemc.h>
struct Command {
int cmdType;
inline bool operator ==(const Command & command) const {
return (command.cmdType == cmdType); }
};
#endif
to compile above code here is the command line:
g++ -I. -I$SYSTEMC_HOME/include -L. -L$SYSTEMC_HOME/lib-linux64
-Wl,-rpath=$SYSTEMC_HOME/lib-linux64 -I/usr/local/include -L/usr/local/lib -lyaml-cpp -o main main.cpp producer.cpp consumer.cpp -lsystemc -lm
Are you sure that sc_trace function is right?
In order to be successful of your call, overloading function of two types is necessary at least. of course, I didn't think that implicit conversion class.
Anyway, two functions are as below:
sc_trace(sc_trace_file, int, string)
sc_trace(sc_trace_file, double, string)
`
inline void sc_trace(sc_trace_file * &tf, const Command & command, string &name)
{
sc_trace(tf, command.cmdType, name + ".cmdType"); // 1
sc_trace(tf, command.lba, name + ".lba"); // 1
sc_trace(tf, command.timestamp, name + ".timestamp"); // 2
sc_trace(tf, command.size, name + ".size"); // 1
}
found the fix!!!
changed stdtype.h as follows
#ifndef __STDTYPE_H__
#define __STDTYPE_H__
#include <queue>
#include <systemc.h>
#include <iomanip>
#include <sstream>
#include <map>
#include <utility>
#include <vector>
#include <string>
using namespace std;
struct Command {
int cmdType;
inline bool operator ==(const Command & command) const {
return (command.cmdType == cmdType); }
};
inline ostream & operator <<(ostream & os, const Command & command)
{
os << "CmdType " << command.cmdType << endl;
return os;
}
inline void sc_trace(sc_trace_file * tf, const Command & command, const string & name)
{
sc_trace(tf, command.cmdType, name + ".cmdType");
}
#endif
and removed these functions from main.cpp, this fixed the issue and i can trace the channel in vcd file, also added other code to communicate through the channel

error: cannot bind ‘std::ostream in implementation file

First: I have tried reading and modifying my code based off no less than 7 other similar questions. At best, the other options trigger an avalanche of errors. With my current code, I'm down to a single error.
Putting it inside the class and using "friend" doesn't work, and using ostream& operator<< (ostream &out, const Fraction &rhs) makes a whole lot more errors.
The frustrating thing is that in c9.io this code works, but not on Netbeans.
In my main.cpp:
#include <iostream>
#include "fraction.h"
using namespace std;
int main() {
Fraction f(3, 4);
cout << f;
return 0;
}
In fraction.h:
#ifndef FRACTION_H
#define FRACTION_H
class Fraction{
public:
//constructor defs
//accessors
//modifiers/mutators
void setNumer(int newNum);
void setDenom(int newDenom);
void reduce();
private:
//instance variables
int numer;
int denom;
//helper functions
int gcd(int a, int b);
};
#endif /* FRACTION_H */
And in fraction.cpp:
#include "fraction.h"
#include <cmath>
#include <iostream>
using namespace std;
//code for constructors
//accessors
int Fraction::getNumer(){
return numer;
}
int Fraction::getDenom(){
return denom;
}
//modifiers/mutators
//other operator definitions
ostream& operator<< (ostream &out, Fraction &rhs){
if(rhs.getNumer() == 0){
out << 0;
} else if(rhs.getNumer() == rhs.getDenom()){
out << 1;
} else {
rhs.reduce();
out << rhs.getNumer() << "/" << rhs.getDenom();
}
}
The output is:
g++ -c -g -std=c++11 -MMD -MP -MF "build/Debug/GNU-Linux/main.o.d" -o build/Debug/GNU-Linux/main.o main.cpp
main.cpp: In function ‘int main()’:
main.cpp:6:13: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
cout << f;
^
In file included from /usr/include/c++/4.8/iostream:39:0,
from main.cpp:1:
/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 = Fraction]’
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
There is no knowledge of the operator<< function that is defined in Fraction.cpp in main.cpp Hence, the line
cout << f;
is a problem.
Add the declaration of the function in the .h file.
#ifndef FRACTION_H
#define FRACTION_H
#include <iostream>
class Fraction{
public:
//constructor defs
//accessors
//modifiers/mutators
void setNumer(int newNum);
void setDenom(int newDenom);
void reduce();
private:
//instance variables
int numer;
int denom;
//helper functions
int gcd(int a, int b);
};
std::ostream& operator<< (std::ostream &out, Fraction const& rhs);
// ^^^^ Using const&, not just Fraction&
#endif /* FRACTION
So the answer was partly what #r-sahu said:
I had to set getNumer() and getDenom() as const member functions BUT I could only get the errors to go away by NOT using const& in the function definition.
Good:
std::ostream& operator<< (std::ostream &out, Fraction rhs);
Not good:
std::ostream& operator<< (std::ostream &out, Fraction const& rhs);
It now compiles and runs. any insight on why making the member functions const but not passing the Fraction as const makes it work? I stumbled on this solution by accident and don't understand it.

error on include the fstream.h header

I am reading a book "Data Structures and Algorithms in C++" which was published at 2001, I think the c++ compiler should be changed a lot since that time, because I found the code in the book can not be compiled.
#include <fstream.h>
#include <string.h>
So I Google for the answer, and changed the code to
#include <fstream>
#include <cstring>
using namespace std;
But when I tried to compile the code, well, I got some error I have not ever seen:
oo#oo:~/raf$ g++ database.cpp personal.cpp student.cpp useDatabase.cpp -o useDatabase
In file included from /usr/include/c++/4.6/ios:45:0,
from /usr/include/c++/4.6/istream:40,
from /usr/include/c++/4.6/fstream:40,
from personal.h:4,
from student.h:1,
from student.cpp:1:
/usr/include/c++/4.6/bits/ios_base.h: In copy constructor ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’:
/usr/include/c++/4.6/bits/ios_base.h:788:5: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
/usr/include/c++/4.6/bits/basic_ios.h:64:11: error: within this context
In file included from /usr/include/c++/4.6/istream:41:0,
from /usr/include/c++/4.6/fstream:40,
from personal.h:4,
from student.h:1,
from student.cpp:1:
/usr/include/c++/4.6/ostream: In copy constructor ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’:
/usr/include/c++/4.6/ostream:57:11: note: synthesized method ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’ first required here
In file included from student.cpp:1:0:
student.h: In function ‘std::ostream& operator<<(std::ostream&, Student&)’:
student.h:17:39: note: synthesized method ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’ first required here
student.h:15:18: error: initializing argument 1 of ‘std::ostream& Student::writeLegibly(std::ostream)’
student.cpp: At global scope:
student.cpp:24:10: error: prototype for ‘std::ostream& Student::writeLegibly(std::ostream&)’ does not match any in class ‘Student’
student.h:15:18: error: candidate is: std::ostream& Student::writeLegibly(std::ostream)
student.cpp: In member function ‘std::istream& Student::readFromConsole(std::istream&)’:
student.cpp:34:5: error: ‘cout’ was not declared in this scope
In file included from /usr/include/c++/4.6/ios:45:0,
from /usr/include/c++/4.6/ostream:40,
from /usr/include/c++/4.6/iostream:40,
from useDatabase.cpp:1:
/usr/include/c++/4.6/bits/ios_base.h: In copy constructor ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’:
/usr/include/c++/4.6/bits/ios_base.h:788:5: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
/usr/include/c++/4.6/bits/basic_ios.h:64:11: error: within this context
In file included from /usr/include/c++/4.6/iostream:40:0,
from useDatabase.cpp:1:
/usr/include/c++/4.6/ostream: In copy constructor ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’:
/usr/include/c++/4.6/ostream:57:11: note: synthesized method ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’ first required here
In file included from useDatabase.cpp:2:0:
student.h: In function ‘std::ostream& operator<<(std::ostream&, Student&)’:
student.h:17:39: note: synthesized method ‘std::basic_ostream<char>::basic_ostream(const std::basic_ostream<char>&)’ first required here
student.h:15:18: error: initializing argument 1 of ‘std::ostream& Student::writeLegibly(std::ostream)’
oo#oo:~/raf$
I spent a lot of time to Google for the answer, but got even more error. Maybe I should register a Github account and upload my code there.
database.cpp
#include "database.h"
template<class T> Database<T>::Database() {
cout << "File name: ";
cin >> fName;
}
template<class T> void Database<T>::add(T& d){
database.open(fName, ios::in|ios::out|ios::binary);
database.seekp(0, ios::end);
d.writeToFile(database);
database.close();
}
template<class T> void Database<T>::modify(const T& d){
T tmp;
database.open(fName, ios::in|ios::out|ios::binary);
while(!database.eof()){
tmp.readFromFile(database);
if (tmp == d){
cin >> tmp;
database.seekp(-d.size(), ios::cur);
tmp.writeToFile(database);
database.close();
return;
}
}
database.close();
cout << "The record to be modified is not in the database\n";
}
template<class T> bool Database<T>::find(const T& d){
T tmp;
database.open(fName, ios::in|ios::binary);
while(!database.eof()){
tmp.readFromFile(database);
if (tmp == d){
database.close();
return true;
}
}
database.close();
return false;
}
template<class T> ostream& Database<T>::print(ostream& out){
T tmp;
database.open(fName, ios::in|ios::binary);
while(1){
tmp.readFromFile(database);
if (database.eof())
break;
out << tmp << endl;
}
database.close();
return out;
}
template<class T> void Database<T>::run() {
char option[5];
T rec;
cout << "1.Add 2.Find 3.Modify a record 4.Exit\n";
cout << "Enter an option: ";
cin.getline(option, 4);
while (cin.getline(option, 4)){
if (*option == '1'){
cin >> rec;
add(rec);
}
else if (*option == '2'){
rec.readKey();
cout << "The record is ";
if (find(rec) == false)
cout << "not ";
cout << "in the database\n";
}
else if (*option == '3'){
rec.readKey();
modify(rec);
}
else if (*option != '4'){
cout << "Wrong option\n";
}
else return;
cout << *this;
cout << "Enter an option";
}
}
database.h
#ifndef DATABASE
#define DATABASE
#include <fstream>
#include <iostream>
using namespace std;
template<class T> class Database{
public:
Database();
void run();
private:
fstream database;
char fName[20];
ostream& print(ostream&);
void add(T&);
bool find(const T&);
void modify(const T&);
friend ostream& operator<<(ostream& out, Database& db) {
return db.print(out);
}
};
#endif
personal.cpp
#include "personal.h"
#include <iostream>
Personal::Personal() : nameLen(10), cityLen(10) {
name = new char[nameLen + 1];
city = new char[cityLen + 1];
}
Personal::Personal(char *ssn, char *n, char *c, int y, long s) : nameLen(10), cityLen(10) {
name = new char[nameLen + 1];
city = new char[cityLen + 1];
strcpy(SSN, ssn);
strcpy(name, n);
strcpy(city, c);
year = y;
salary = s;
}
void Personal::writeToFile(fstream& out) const {
out.write(SSN, 9);
out.write(name, nameLen);
out.write(city, cityLen);
out.write(reinterpret_cast<const char*>(&year), sizeof(int));
out.write(reinterpret_cast<const char*>(&salary), sizeof(int));
}
void Personal::readFromFile(fstream& in) {
in.read(SSN, 9);
in.read(name, nameLen);
in.read(city, cityLen);
in.read(reinterpret_cast<char *>(&year), sizeof(int));
in.read(reinterpret_cast<char *>(&salary), sizeof(int));
}
void Personal::readKey() {
char s[80];
cout << "Enter SSN: ";
cin.getline(s, 80);
strncpy(SSN, s, 9);
}
ostream& Personal::writeLegibly(ostream& out){
SSN[9] = name[nameLen] = city[cityLen] = '\0';
out << "SSN = " << SSN << ", name = " << name
<< ", city = " << city << ", year = " << year
<< ", salary = " << salary;
return out;
}
istream& Personal::readFromConsole(istream& in){
char s[80];
cout << "SSN: ";
in.getline(s, 80);
strncpy(SSN, s, 9);
cout << "Name: ";
in.getline(s, 80);
strncpy(name, s, nameLen);
cout << "City: ";
in.getline(s, 80);
strncpy(city, s, cityLen);
cout << "Birthyear: ";
in >> year;
cout << "Salary: ";
in >> salary;
in.getline(s, 80); //get '\n'
return in;
}
personal.h
#ifndef PERSONAL
#define PERSONAL
#include <fstream>
#include <cstring>
using namespace std;
class Personal {
public:
Personal();
Personal(char*, char*, char*, int, long);
void writeToFile(fstream&) const;
void readFromFile(fstream&);
void readKey();
int size() const {
return 9 + nameLen + cityLen + sizeof(year) + sizeof(salary);
}
bool operator==(const Personal& pr) const{
return strcmp(pr.SSN, SSN) == 0;
}
protected:
const int nameLen, cityLen;
char SSN[10], *name, *city;
int year;
long salary;
ostream& writeLegibly(ostream&);
friend ostream& operator<<(ostream& out, Personal& pr){
return pr.writeLegibly(out);
}
istream& readFromConsole(istream&);
friend istream& operator>>(istream& in, Personal& pr){
return pr.readFromConsole(in);
}
};
#endif
student.cpp
#include "student.h"
Student::Student() : majorLen(10) {
Personal();
major = new char[majorLen + 1];
}
Student::Student(char *ssn, char *n, char *c, int y, long s, char *m): majorLen(11){
Personal(ssn, n, c, y, s);
major = new char[majorLen + 1];
strcpy(major, m);
}
void Student::writeToFile(fstream& out) const {
Personal::writeToFile(out);
out.write(major, majorLen);
}
void Student::readFromFile(fstream& in) {
Personal::readFromFile(in);
in.read(major, majorLen);
}
ostream& Student::writeLegibly(ostream &out){
Personal::writeLegibly(out);
major[majorLen] = '\0';
out << ", major = " << major;
return out;
}
istream& Student::readFromConsole(istream& in){
Personal::readFromConsole(in);
char s[80];
cout << "Major: ";
in.getline(s, 80);
strncpy(major, s, 9);
return in;
}
student.h
#include "personal.h"
class Student : public Personal {
public:
Student();
Student(char*, char*, char*, int, long, char*);
void writeToFile(fstream&) const;
void readFromFile(fstream&);
int size() const{
return Personal::size() + majorLen;
}
protected:
char *major;
const int majorLen;
ostream& writeLegibly(ostream);
friend ostream& operator<<(ostream& out, Student& sr){
return sr.writeLegibly(out);
}
istream& readFromConsole(istream&);
friend istream& operator>>(istream& in, Student& sr){
return sr.readFromConsole(in);
}
};
useDatabase.cpp
#include <iostream>
#include "student.h"
#include "personal.h"
#include "database.h"
int main(){
Database<Personal> db;
db.run();
}
This was a big — arguably too big — set of files to be analyzed in an SO question. You need to learn some methods of reducing the size of your problem for presentation to SO (or to Tech Support).
One of the first steps in C or C++ is to ensure that the headers you create compile cleanly. If the headers aren't clean, you won't be able to compile the code that uses the headers, so headers must be sorted out first.
To help me, I have a script that I call chkhdr:
#!/bin/sh
# Check whether headers compile
tmp=chkhdr-$$
trap 'rm -f $tmp.?; exit 1' 0 1 2 3 13 15
cat > $tmp.c <<EOF
#include HEADER /* Check self-containment */
#include HEADER /* Check idempotence */
int main(void) { return 0; }
EOF
options=
for file in "$#"
do
case "$file" in
(-*) options="$options $file";;
(*) echo "$file"
${CC:-gcc} $options -DHEADER="\"$file\"" -c $tmp.c
;;
esac
done
rm -f $tmp.?
trap 0
I use it to check that headers are both self-contained and idempotent. A self-contained header can be included without any other headers before it, and it compiles. That means it can be used anywhere its services are needed without further ado. An idempotent header can be included multiple times without causing trouble. (I mainly work in C, hence the default compiler is GCC rather than G++. But I can set CC=g++ in the environment to switch to C++ work.)
Your student.h header was not idempotent; I immediately added the standard stanzas at top and bottom:
#ifndef STUDENT_H_INCLUDED
#define STUDENT_H_INCLUDED
...original contents of student.h...
#endif /* STUDENT_H_INCLUDED */
The detailed choice of guard macro name is up to you; that's the naming scheme I use these days, but there's some merit in using something like an MD5 checksum of an draft of the header to give you a quasi-random guard macro.
The output from compiling the student.h header alone was:
In file included from chkhdr-8120.c:1:
/usr/include/c++/4.2.1/bits/ios_base.h: In copy constructor ‘std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’:
/usr/include/c++/4.2.1/bits/ios_base.h:779: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
/usr/include/c++/4.2.1/iosfwd:55: error: within this context
/usr/include/c++/4.2.1/iosfwd: In copy constructor ‘std::basic_ostream<char, std::char_traits<char> >::basic_ostream(const std::basic_ostream<char, std::char_traits<char> >&)’:
/usr/include/c++/4.2.1/iosfwd:64: note: synthesized method ‘std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’ first required here
student.h: In function ‘std::ostream& operator<<(std::ostream&, Student&)’:
student.h:20: note: synthesized method ‘std::basic_ostream<char, std::char_traits<char> >::basic_ostream(const std::basic_ostream<char, std::char_traits<char> >&)’ first required here
student.h:20: error: initializing argument 1 of ‘std::ostream& Student::writeLegibly(std::ostream)’
The last line of the error message points firmly at the issue; the other messages are somewhat tangential, and lead up to the crux message. (Very often, especially in C, the first error is the most significant. It was surprising to me that the last line was the key one.) Changing line 20 of student.h to read:
ostream& writeLegibly(ostream&);
resolved that problem, and the student.h header compiled cleanly. The other headers were also clean. Then it was a simple matter to compile the source files. Only student.cpp had an issue:
student.cpp: In member function ‘std::istream& Student::readFromConsole(std::istream&)’:
student.cpp:34: error: ‘cout’ was not declared in this scope
It sounds like a case of 'should use std::cout instead', but adding that leads to:
student.cpp: In member function ‘std::istream& Student::readFromConsole(std::istream&)’:
student.cpp:34: error: ‘cout’ is not a member of ‘std’
That is fixed by including #include <iostream>. Then the code compiles cleanly under:
g++ -c *.cpp
I can't link; I run into undefined references to the Database code, but that's not surprising.
Summary
The details of the fixes are not incredibly important. What is important is the techniques. The key techniques here are:
Ensure headers work cleanly on their own (chkhdr).
Tackle one file at a time.
Problem minimization.
We should not have had to deal with all the code; you should have been able to isolate the problems much better. This is an important skill in any situation where you're reporting software problems to others. Eliminate the extraneous, and reduce to bare essentials.
the errors report
student.cpp:34:5: error: ‘cout’ was not declared in this scope
I think you need
#include <iostream>
In Student change
ostream& writeLegibly(ostream);
to
ostream& writeLegibly(ostream&);
and that should fix a lot. By missing the ampersand you were trying to copy the stream.
While the compiler have changed C++ and C are backwards compatible. One of the strengths of the language. Anyway I have copied out your code into a VS2010 because it was easier for me to analyse the issues with it.
put the #include < iostream > in your personal.h. It is used by personal.cpp where you have a cout.
The signature in student.h of
ostream& writeLegibly(ostream);
is wrong, it should be:
ostream& writeLegibly(ostream&);
I have moved the implementation code in database.cpp into the database.h. Plain simple cut and paste above the #endif. Due to the template nature the compiler did not like it that it was in a separate implementation cpp.
Hope that helps.

template class, friend operator << overload

I'm trying to overload the "<<" operator for a template class. I've the definition of the class in a .h file and its implementation in a .cpp file.
/tmp/ccjJIJhO.o: In function `main':
main.cpp:(.text+0xad): undefined reference to `std::basic_istream<char, std::char_traits<char> >& operator>><int>(std::basic_istream<char, std::char_traits<char> >&, FeatureVector<int>&)'
main.cpp:(.text+0xba): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, FeatureVector<int> const&)'
collect2: ld returned 1 exit status
The class definition:
common.h
#include <iostream>
using namespace std;
featurevector.h
#ifndef FEATURE_VECTOR_H
#define FEATURE_VECTOR_H
#include <common.h>
template < class FEAT_TYPE >
class FeatureVector;
template < class FEAT_TYPE >
istream & operator >> (istream &, FeatureVector<FEAT_TYPE> &);
template < class FEAT_TYPE >
ostream & operator << (ostream &, const FeatureVector<FEAT_TYPE> &);
template < class FEAT_TYPE >
class FeatureVector{
public:
FeatureVector(int = 0);
...
friend istream & operator >> <>(istream &, FeatureVector<FEAT_TYPE> & );
friend ostream & operator << <>(ostream &, const FeatureVector<FEAT_TYPE> &);
...
~FeatureVector();
private:
int m_nDim;
FEAT_TYPE * m_pFeat;
};
#endif
featurevector.cpp
#include <featurevector.h>
...
template < class FEAT_TYPE >
istream & operator >> (istream & input, FeatureVector< FEAT_TYPE> & refFeat ){
int d;
for(d=0; d < refFeat.getDim(); d++){
input >> refFeat.m_pFeat[d];
}
return (input);
}
template < class FEAT_TYPE >
ostream & operator << (ostream & output, const FeatureVector< FEAT_TYPE > & refFeat ){
int d;
for(d=0; d < refFeat.getDim(); d++){
output << refFeat.m_pFeat[d] << " ";
}
output << endl;
return (output);
}
...
#include "featurevector-impl.cpp"
featurevector-impl.cpp
template class FeatureVector<int>;
//template istream & operator >> <>(istream &, FeatureVector<int> &);
//template ostream & operator << <>(ostream &, const FeatureVector<int> &);
mylib.h
#ifndef MY_LIB_H
#define MY_LIB_H
#include <featurevector.h>
#endif
main.cpp
#include <mylib.h>
#include <common.h>
int main(){
FeatureVector<int> pFeat(10);
cin >> (pFeat);
cout << (pFeat);
return (0);
}
Makefile associated with "mylib"
INC=./inc
SRC=./src
LIB=./lib
OBJ=./obj
CC=g++
CFLAGS=-O3 -Wall
mylib: $(LIB)/mylib.a
echo "mylib was created!..."
$(LIB)/mylib.a: \
$(OBJ)/featurevector.o
ar csr $(LIB)/mylib.a \
$(OBJ)/featurevector.o
$(OBJ)/featurevector.o: $(SRC)/featurevector.cpp
$(CC) -c $(CFLAGS) $(SRC)/featurevector.cpp -I$(INC) \
-o $(OBJ)/featurevector.o
clean:
rm -rf $(LIB)/*.a
rm -rf $(OBJ)/*.o
Makefile for main.cpp (the main.cpp with its Makefile are under an "app" directory)
LIB=../lib
INC=../inc
OBJ=../obj
BIN=../bin
CC=g++
CFLAGS=-O3 -Wall
LFLAGS=-lmylib -lm
$#.cpp: $(LIB)/mylib.a $#.cpp
cd ..; make; cd app;
$(CC) $(CFLAGS) $#.cpp -o $(BIN)/$# -I$(INC) -L$(LIB) $(LFLAGS)
clean:
rm -rf $(BIN)/*
According to this, you have to make the function known as template in your class definition.
class.h
#include <iostream>
using std::ostream;
template <typename T>
class A {
public:
...
template <typename J> // <-- CAUTION!
friend ostream &operator<<(ostream &output, const A<J> &a);
};
class.cpp
#include "class.h"
...
template <typename T>
ostream &operator<<(ostream &output, const A<T> &a) {
// Your implementation
return output;
}
...
template ostream &operator<<(ostream &output, const A<int> &a);
template ostream &operator<<(ostream &output, const A<float> &a);
If the line template <typename J> is removed, the compilation error "underfined reference" comes.
See FAQ item 35.12 Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?.
Your posted error code says that it is operator>> that is throwing an unresolved external error, not operator<<. In addition, your code won't compile because there is no convert constructor on myClass taking an int. So you have not posted the correct code.
But this works:
#include <iostream>
using namespace std;
template < class T >
class myClass;
template < class T >
ostream & operator << (ostream &, const myClass<T> &);
template < class T >
class myClass{
public:
myClass(int) {}
friend ostream & operator << <>(ostream &, const myClass<T> &);
private:
T m_Data;
};
template < class T >
ostream & operator << (ostream & out, const myClass<T> & refClass){
out << refClass.m_Data << endl;
return (out);
}
myClass<int>;
myClass<float>;
int main(int argc, char **argv){
myClass<int> test(5);
cout << test;
return 0;
}
Don't make it so complicated:
template<class FEAT_TYPE>
struct FeatureVector {
FeatureVector(int = 0);
friend std::istream& operator>>(std::istream &s, FeatureVector &x) {
for(int d = 0; d < x.getDim(); d++) {
s >> x.m_pFeat[d];
}
return s;
}
friend std::ostream& operator<<(std::ostream &s, FeatureVector const &x) {
// since you're terminating with " " rather than separating:
copy(x.m_pFeat, x.m_pFeat + x.getDim(), ostream_iterator<FEAT_TYPE>(s, " "));
s << endl;
return s;
}
//...
featurevector-impl.cpp is incorrect. Explicit template instantiations look like this:
template class FeatureVector<int>;
Since the operators aren't members, they must also be explicitly instantiated:
template istream & operator >> <>(istream &, FeatureVector<int> &);
I don't recommend splitting up your template definitions like this, though, unless you're really keen on micromanaging which specific classes will work with your template (which kind of goes against the spirit of using a template).