Multiple output operators? - c++

is it possible to define multiple output operators for an enum? I want to use this
std::ostream& operator<< (std::ostream& os, my_enum e);
operator to (1) print a human readable text and to (2) convert it to some code for storing in a database.
Thanks

Create wrappers which will return some object instead of ostream& which will handle printing. In your case it will object for printing humand-readable value and object for printing database code. Here's rough example which prints human-readable form and integer form. ostream_enum_wrapper_human class with its operator << is used for printing human-readable form, class ostream_enum_wrapper_int with its << is used for printing integer code. To switch from ostream& to wrapper, operator << (ostream&, wrappertag) is used, which wraps ostream object inside of wrapper and returns wrapped object. So next << operator is called on wrapper object, not on ostream&, and wrapper class knows how to print value.
#include <iostream>
using namespace std;
class ostream_enum_wrapper_human
{
public:
ostream& out;
ostream_enum_wrapper_human(std::ostream& _out) : out(_out){}
};
class ostream_enum_wrapper_int
{
public:
std::ostream& out;
ostream_enum_wrapper_int(std::ostream& _out) : out(_out){}
};
enum T{zero,one,two};
struct human_readable{} HumanReadable;
ostream_enum_wrapper_human operator << (ostream& out, human_readable){
return ostream_enum_wrapper_human(out);
}
struct print_int{} PrintInt;
ostream_enum_wrapper_int operator << (ostream& out, print_int){
return ostream_enum_wrapper_int(out);
}
ostream& operator << (ostream_enum_wrapper_human out, T t)
{
switch(t) {
case zero: out.out << "zero"; break;
case one: out.out << "one"; break;
case two: out.out << "two"; break;
}
return out.out;
}
ostream& operator << (ostream_enum_wrapper_int out, T t)
{
return out.out << static_cast<int>(t);
}
int main()
{
cout << HumanReadable << zero << PrintInt << zero << HumanReadable << two;
}
prints zero0two

You may take advantage of overloading by the first argument.
//For human-readable output
std::ostream& operator<< (std::ostream& os, my_enum e);
//For database; note the absence VVV of & sign here
std::ostream& operator<< (databasefmt fmt, my_enum e)
{
std::ostream& os = fmt.stream;
// Write data to os
// ...
return os;
}
struct databasefmt{
std::ostream& stream;
databasefmt(std::ostream & s) : stream(s) {};
};
Then write stream modifier that converts the stream to wrapping databasefmt class, so that next output to that modified stream would be database output for you enum. The printing code would look like this:
output_stream << "DATA: "<< database_format << my_enum::Value << "END OF DATA" ;
// Type: std::ostream | databasefmt | std::ostream |
and the wrapper like this:
//Variable is needed to avoid confusing parentheses in output operators
struct databasefmt_converter_t {} database_format;
// we can't return reference, so we just return fairly small instance of wrapper
databasefmt operator<< (std::ostream& os, databasefmt_converter_t const&)
{ return databasefmt(os); }

Sure why not? You would have to create an ostream derived class which implements writing to the database, much the same as ofstream writes to a file. The devil is in the details.

The preferred way is to use std::ios_base::xalloc and then std::ios_base::iword:
int getxalloc()
{
static const int ix = std::ios_base::xalloc();
return ix;
}
enum my_enum
{
zero,
one,
two,
};
std::ostream& operator<<(std::ostream& os, my_enum e)
{
switch (os.iword(getxalloc())
{
default:
case 0:
os << (int)e;
break;
case 1:
switch (e)
{
case zero:
os << "zero";
break;
case one:
os << "one";
break;
case two:
os << "two";
break;
default:
os << "unknown";
break;
}
break;
}
return os;
}
int main()
{
my_enum e = one;
std::cout.iword(getxalloc()) = 0;
std::cout << e << "\n"; // will output "1"
std::cout.iword(getxalloc()) = 1;
std::cout << e << "\n"; // will output "one"
}
After that you could add some fancy manipulator of your own, instead of using std::ios_base::iword directly. Like this:
inline std::ios_base& format_my_enum_as_int(std::ios_base& ib)
{
ib.iword(getxalloc()) = 0;
return ib;
}
inline std::ios_base& format_my_enum_as_string(std::ios_base& ib)
{
ib.iword(getxalloc()) = 1;
return ib;
}
int main()
{
my_enum e = one;
std::cout << format_my_enum_as_int << e << "\n"; // will output "1"
std::cout << format_my_enum_as_string << e << "\n"; // will output "one"
}

This solution is far from perfect; but there is no really nice one to your problem.
class MyClass {...};
namespace xml
{
std::ostream& operator << (std::ostream& os, MyClass& c);
}
namespace text
{
std::ostream& operator << (std::ostream& os, MyClass& c);
}
As you can see I put the stream operators in namespaces. As a result I have to include the namespace into the current one. This is simply done with a simple using declaration.
using namespace xml;
The trick is to put the using declaration in the smalest scope possible.

Related

Why is my cout statement giving me an error? [duplicate]

myclass is a C++ class written by me and when I write:
myclass x;
cout << x;
How do I output 10 or 20.2, like an integer or a float value?
Typically by overloading operator<< for your class:
struct myclass {
int i;
};
std::ostream &operator<<(std::ostream &os, myclass const &m) {
return os << m.i;
}
int main() {
myclass x(10);
std::cout << x;
return 0;
}
You need to overload the << operator,
std::ostream& operator<<(std::ostream& os, const myclass& obj)
{
os << obj.somevalue;
return os;
}
Then when you do cout << x (where x is of type myclass in your case), it would output whatever you've told it to in the method. In the case of the example above it would be the x.somevalue member.
If the type of the member can't be added directly to an ostream, then you would need to overload the << operator for that type also, using the same method as above.
it's very easy, just implement :
std::ostream & operator<<(std::ostream & os, const myclass & foo)
{
os << foo.var;
return os;
}
You need to return a reference to os in order to chain the outpout (cout << foo << 42 << endl)
Even though other answer provide correct code, it is also recommended to use a hidden friend function to implement the operator<<. Hidden friend functions has a more limited scope, therefore results in a faster compilation. Since there is less overloads cluttering the namespace scope, the compiler has less lookup to do.
struct myclass {
int i;
friend auto operator<<(std::ostream& os, myclass const& m) -> std::ostream& {
return os << m.i;
}
};
int main() {
auto const x = myclass{10};
std::cout << x;
return 0;
}
Alternative:
struct myclass {
int i;
inline operator int() const
{
return i;
}
};

How to custom Class to_string for std::cout

I find following boost code
for (auto entry : boost::make_iterator_range(boost::filesystem::directory_iterator(dir_path), {})) {
std::cout << entry << std::endl;
}
entry can be output with dir path, I guess c++ has feature like java Class#toString to custom output string, I try following code:
class C {
str to_string() {
return "prpr";
}
};
TEST_F(FileTest, Draft1) {
C c;
std::cout << c << std::endl;
}
I expect output "prpr", but it doesn't work, how to fix it?
C++ doesn't call any "to_string" or similar function automatically. Instead you must overload the operator<< function for your class:
class C
{
public:
friend std::ostream& operator<<(std::ostream& os, C const& c)
{
return os << "prpr";
}
};
If you want to pass a class to std::cout you need to overload the << operator for std::ostream in your class.
class C {
friend std::ostream& operator<<(std::ostream& os, const C& c);
};
std::ostream& operator<<(std::ostream& os, const C& c){
os<<"prpr";
return os;
}

Invoking specialized ostream operator

I have the following code...
#include <sstream>
enum class eTag
{
A,
B,
C
};
template<eTag I> std::ostream& operator<< (std::ostream& str, int i)
{
return str; // do nothing
}
template<> std::ostream& operator<< <eTag::A>(std::ostream& str, int i)
{
return str << "A:" << i; // specialize for eTag::A
}
template<> std::ostream& operator<< <eTag::B>(std::ostream& str, int i)
{
return str << "B:" << i; // specialize for eTag::B
}
template<> std::ostream& operator<< <eTag::C>(std::ostream& str, int i)
{
return str << "C:" << i; // specialize for eTag::C
}
int main()
{
std::ostringstream s;
// s << <eTag::A>(42) << std::endl;
return 0;
}
This compiles. But as you can see from the commented line in main(), I'm struggling with how to actually invoke a specialization of the ostream operator.
Quick answer:
operator<< <eTag::A>(std::cout,42);
I think you're much better off with implementing your own template-class manipulator that friends ostream& operator<<(ostream&), and keeps the state as a member variable (initialized via a constructor). See here (except for the template-part)
operator<<<eTag::A>(std::cout, 42) << std::endl;
(You can add a space between operator<< and the template argument list if you want. Doesn't make a difference.)
This is pretty nasty. Usually we don't write operators that require explicit template arguments. Better to do something like this:
inline std::ostream& operator<<(std::ostream& os, eTag x) {
if (x == eTag::A) {
return os << "A:";
} else if (x == eTag::B) {
return os << "B:";
} else if (x == eTag::C) {
return os << "C:";
} else {
throw std::range_error("Out of range value for eTag");
}
}
Then:
std::cout << eTag::A << 42 << std::endl;
A good compiler will be able to inline this, so your code will be as efficient as if you had just typed
std::cout << "A:" << 42 << std::endl;

lexical cast from user defined type to int

I am trying to use boost::lexical_cast to convert my user defined type into an integer.
However, I get an exception. What am I missing??
class Employee {
private:
string name;
int empID;
public:
Employee() : name(""), empID(-1)
{ }
friend ostream& operator << (ostream& os, const Employee& e) {
os << e.empID << endl;
return os;
}
/*
operator int() {
return empID;
}*/
};
int main() {
Employee e1("Rajat", 148);
int eIDInteger = boost::lexical_cast<int>(e1); // I am expecting 148 here.
return 0;
}
I know I can always use the conversion operator, but just wondering why lexical cast doesn't work here.
The problem is that what you insert into the output stream is not the representation of an integer (because of the trailing << std::endl). The following fails in a similar way:
boost::lexical_cast<int>("148\n")
Removing the << std::endl makes it work:
friend std::ostream& operator << (std::ostream& os, const Employee& e) {
os << e.empID;
// ^^^^^^^^^^^^^^
// Without << std::endl;
return os;
}

How can I use cout << myclass

myclass is a C++ class written by me and when I write:
myclass x;
cout << x;
How do I output 10 or 20.2, like an integer or a float value?
Typically by overloading operator<< for your class:
struct myclass {
int i;
};
std::ostream &operator<<(std::ostream &os, myclass const &m) {
return os << m.i;
}
int main() {
myclass x(10);
std::cout << x;
return 0;
}
You need to overload the << operator,
std::ostream& operator<<(std::ostream& os, const myclass& obj)
{
os << obj.somevalue;
return os;
}
Then when you do cout << x (where x is of type myclass in your case), it would output whatever you've told it to in the method. In the case of the example above it would be the x.somevalue member.
If the type of the member can't be added directly to an ostream, then you would need to overload the << operator for that type also, using the same method as above.
it's very easy, just implement :
std::ostream & operator<<(std::ostream & os, const myclass & foo)
{
os << foo.var;
return os;
}
You need to return a reference to os in order to chain the outpout (cout << foo << 42 << endl)
Even though other answer provide correct code, it is also recommended to use a hidden friend function to implement the operator<<. Hidden friend functions has a more limited scope, therefore results in a faster compilation. Since there is less overloads cluttering the namespace scope, the compiler has less lookup to do.
struct myclass {
int i;
friend auto operator<<(std::ostream& os, myclass const& m) -> std::ostream& {
return os << m.i;
}
};
int main() {
auto const x = myclass{10};
std::cout << x;
return 0;
}
Alternative:
struct myclass {
int i;
inline operator int() const
{
return i;
}
};