I'm trying to make a C++ class resembling std::ostream, that will take its input and write to two std::ostreams given in the constructor. Here it is together with appropriate operator<< template:
struct SplitStream
{
SplitStream(std::ostream & a_, std::ostream & b_) : a(a_), b(b_) {}
std::ostream & a, & b;
};
template<class T>
const SplitStream & operator << (const SplitStream & sp, const T & x)
{
sp.a << x;
sp.b << x;
return sp;
}
Several lines below that code, I try to use this class:
void foo(SplitStream & out)
{
double some_double = 1.23;
out << "bar" << some_double << std::endl;
}
And I get this rather enigmatic error:
... error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'const SplitStream' (or there is no acceptable conversion) ...
What am I doing wrong? I tried to define operator<< without consts, and it didn't compile either.
The immediate problem is that std::endl isn't an object but a function template declared something like this:
template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& endl(std::basic_ostream<cT, Traits>&);
To use a function pointer like this, the template arguments need to be deduced. To this end, the class std::basic_ostream<cT, Traits> declared suitable overloads for operator<<():
template <typename cT, typename Traits>
std::basic_ostream<cT, Traits>& std::baisic_ostream<cT, Traits>::operator<< (
std::basic_ostream<cT, Traits>& (*manip)(std::basic_ostream<cT, Traits>&));
This way, the compiler can deduce the correct instantiation when the std::endl function is referenced.
However, all that is utterly irrelevant because what you are trying to do is better done entirely differently! You should create a suitable stream buffer and use a reasonably constructed std::ostream with this custom stream buffer. Below is a complete example how to do it properly (I had posted it before but only a couple dozens times...):
#include <streambuf>
struct teebuf
: std::streambuf
{
std::streambuf* sb1_;
std::streambuf* sb2_;
teebuf(std::streambuf* sb1, std::streambuf* sb2)
: sb1_(sb1), sb2_(sb2) {
}
int overflow(int c) {
typedef std::streambuf::traits_type traits;
bool rc(true);
if (!traits::eq_int_type(traits::eof(), c)) {
traits::eq_int_type(this->sb1_->sputc(c), traits::eof())
&& (rc = false);
traits::eq_int_type(this->sb2_->sputc(c), traits::eof())
&& (rc = false);
}
return rc? traits::not_eof(c): traits::eof();
}
int sync() {
bool rc(true);
this->sb1_->pubsync() != -1 || (rc = false);
this->sb2_->pubsync() != -1 || (rc = false);
return rc? 0: -1;
}
};
#include <fstream>
#include <iostream>
int main()
{
std::ofstream fout("tee.txt");
teebuf sbuf(fout.rdbuf(), std::cout.rdbuf());
std::ostream out(&sbuf);
out << "hello, world!\n";
}
The other answer is better, but for completeness:
The SplitStream references in your operator<< should not be const, since they are modifying the streams that the struct contains.
template<class T>
SplitStream & operator << (SplitStream & sp, const T & x)
{
sp.a << x;
sp.b << x;
return sp;
}
Related
I have a program that has a base class Value with multiple subclasses (e.g. IntValue) that inherit from Value. Each of these classes have constructors that accept one or more parameters. Here is example code showing what I'd like to be able to do:
#include <iostream>
class Value {
public:
Value() {}
virtual void print(std::ostream& os) const {}
};
class IntValue: public Value {
public:
IntValue(int val): val_(val) {}
void print(std::ostream& os) const override { os << val_; }
private:
int val_;
};
class VariableValue: public Value {
public:
VariableValue(const std::string& name): name_(name) {}
void print(std::ostream& os) const override { os << name_; }
private:
const std::string name_;
};
void emit_add(const Value& lhs, const Value& rhs, std::ostream& os) {
lhs.print(os);
os << " + ";
rhs.print(os);
os << std::endl;
}
template <class ValueType>
void emit_add(const ValueType& lhs, const ValueType& rhs, std::ostream &os) {
lhs.print(os);
os << " + ";
rhs.print(os);
os << std::endl;
}
int main() {
// all these work
emit_add<IntValue>(12, 13, std::cout); // implicit constructors
emit_add<VariableValue>(std::string("x"), std::string("y"), std::cout); // implicit constructo\
rs
emit_add(VariableValue(std::string("x")), IntValue(1), std::cout); // implicit upcasting
// this doesn't
emit_add(std::string("x"), 13, std::cout); // implicit constor + implicit upcasting
return -1;
}
When I try to compile using clang 9.1.0, I get the following error:
test.cpp:47:3: error: no matching function for call to 'emit_add'
emit_add(std::string("x"), 13, std::cout); // implicit constor + implicit upcasting
^~~~~~~~
test.cpp:25:6: note: candidate function not viable: no known conversion from 'std::string' (aka
'basic_string<char, char_traits<char>, allocator<char> >') to 'const Value' for 1st
argument
void emit_add(const Value& lhs, const Value& rhs, std::ostream& os) {
^
test.cpp:33:6: note: candidate template ignored: deduced conflicting types for parameter
'ValueType' ('std::__1::basic_string<char>' vs. 'int')
void emit_add(const ValueType& lhs, const ValueType& rhs, std::ostream &os) {
^
1 error generated.
My understanding is that the compiler is failing to call the implicit constructor for VariableValue AND THEN upcast it to type Value, but it can clearly do both individually.
Is it possible to force the compiler to do this?
A VariableValue is a Value (because inheritance is an "is a" relationship), but Value is not an VariableValue (the "is a" relationship of inheritance is one-way).
What I'm trying to say is that if you have a VariableValue object, you can easily go up the inheritance chain to get a Value object (or reference of it). But you can't go the other way, down the inheritance chain from a Value object, without being explicit about it.
You need to explicitly construct a VariableValue object and pass it to your function:
emit_add(VariableValue(x), 13, std::cout);
Consider the following as counter-example:
class Value
{
public:
Value() { }
Value(int) { }
Value(std::string const&) { }
};
emit_add(x, 13, std::cout);
This now would have worked as the compiler sees emit_add accepting two Values and Value having appropriate non-explicit constructors accepting std::string and int.
What C++ does not provide is inferring derived classes from base class according to given arguments, as Some programmer dude denoted already.
You could, though, provide a wrapper to do this work for you:
class Wrapper
{
std::unique_ptr<Value> value;
public:
Wrapper(int n) : value(new IntValue(n)) { }
Wrapper(std::string) : value(new VariableValue(n)) { }
friend std::ostream& operator<<(std::ostream& s, Wrapper const& w)
{
w.value->print(s);
return s;
}
};
If that's really better than specifying the types directly (as Some programmer dude did) is a matter of taste. On the other hand, as defined above (with operator<<), you now can do:
void emit_add(Wrapper const& lhs, Wrapper const& rhs, std::ostream& os)
{
os << lhs << " + " << rhs << std::endl;
}
which is a little more comfortable as well...
Another approach could be an overloaded template:
void emit_add(Value const& x, Value const& y, std::ostream& os);
template <typename TX, typename TY>
void emit_add(TX&& x, TY&& y, std::ostream& os)
{
emit_add
(
static_cast<Value const&>(TheValue<TX>(std::forward<TX>(x))),
static_cast<Value const&>(TheValue<TY>(std::forward<TY>(y))),
os
);
}
The casts above are necessary as otherwise, the template itself would be a better match and the non-template would not be selected, resulting in endless recursion. I converted the concrete values into a template for:
template <typename T>
class TheValue : public Value
{
public:
TheValue(T&& t)
: val_(std::forward<T>(t))
{ }
void print(std::ostream& os) const override
{
os << val_;
}
private:
T val_;
};
If this default pattern does not match your concrete needs for a specific type, you can specialise it for that type to suite your needs.
If you still need the original type names, you can alias them:
using IntValue = TheValue<int>;
Finally, if it is solely for printing out, you can do it directly, circumventing the Value class entirely:
template <typename TX, typename TY>
void emit_add(TX&& x, TY&& y, std::ostream& os)
{
std::cout << std::forward<TX>(x) << " + " << std::forward<TY>(y) << std::endl;
}
If you now have some custom types you want to print, just provide an operator<< overload for, such as for the following point example:
template <typename T>
class Point
{
T m_x, m_y;
public:
// constructors, calculations, ... (whatever you might need/find useful)
friend ostream& operator<<(ostream& s, Point const& p)
{
s << '(' p.m_x << ", " << p.m_y << ')';
}
};
Side note: The friend operator as above is convenient for your own data types (it still defines a free standing function), just if you did:
template <typename T>
ostream& operator<<(ostream& s, Point<T> const& p)
{
s << '(' p.x() << ", " << p.y() << ')';
}
outside the class (you still can declare it friend inside; if you don't or can't, you cannot use private members, of course, so you rely on the public interface as demonstrated above, assuming x and y are the public getters).
I have a very simple inline helper class called IpAddress, which has 2 overloads of operator << to either serialize an object to a set of custom binary streams (operator as template function) or to output it to a std::ostream (non-template operator function).
#include <cstdint>
#include <string>
#include <array>
#include <iostream>
#include <sstream>
typedef uint8_t byte;
class IpAddress: public std::array<byte,4>
{
// ...
template<class S>
inline friend S& operator<<(S& left, const IpAddress& right) {
left.setBytes(right.data(), 4);
return left;
}
inline friend std::ostream& operator<< (std::ostream& left, const IpAddress& right) {
// do stuff eligible for an ostream
return left;
}
inline operator std::string() {
std::stringstream stream;
stream << *this;
return stream.str();
}
}
As you can see, there is also an operator to convert the address to a string. Unfortunately, the << call inside is selecting the wrong operator<< (the template one), leading to a compiler error:
error: C2039: 'setBytes' : is not a member of 'std::basic_stringstream<char,std::char_traits<char>,std::allocator<char>>'
Why is the compiler (MSVC in this case) selecting the wrong overload with a non-working body? Why not the "more specialized" std::ostream operator? How do I change this behaviour? Thanks!
You don't post a complete, compilable example so I can't see the call site.
However, the problem is most likely because whatever you are streaming out to is not exactly an ostream. It's likely to be derived from an ostream. In which case, template T will be a better match.
EDIT:
Style comments aside (they are right and you would do well to listen), here is a fix:
#include <iostream>
#include <utility>
#include <cstdint>
#include <array>
#include <sstream>
template<class T> static constexpr bool IsAnOstream = std::is_base_of<std::decay_t<T>, std::ostream>::value;
using byte = std::uint8_t;
struct IpAddress: public std::array<byte,4>
{
// ...
template<class S, std::enable_if_t<not IsAnOstream<S>>* = nullptr>
friend S& operator<<(S& left, const IpAddress& right) {
left.setBytes(right.data(), 4);
return left;
}
friend std::ostream& operator<< (std::ostream& left, const IpAddress& right) {
// do stuff eligible for an ostream
return left;
}
/*
* this is a bad idea - it can lead to all kinds of confusion
*
inline operator std::string() {
std::stringstream stream;
stream << *this;
return stream.str();
}
*/
};
// this is better - it's less surprising.
std::string to_string(const IpAddress& r)
{
std::stringstream stream;
stream << *this;
return stream.str();
}
struct MyStream
{
void setBytes(const uint8_t* p, size_t len) {}
};
int main()
{
IpAddress a;
MyStream s;
std::cout << a;
s << a;
return 0;
}
In my project I use a class class called Message which inherits from std::ostringstream to print out human readable information of other class types.
So its << operator is overloaded several times taking my own class types which I want to print out.
class Message : public ostringstream
{
public:
Message() {};
virtual ~Message() {};
Message& operator <<(const MyTypeA &a) { return *this << a.getStr(); };
Message& operator <<(const MyTypeB &b) { return *this << b.identifier(); };
Message& operator <<(const MyTypeC &c) { return *this << c.foo(); };
// Pass everything unknown down to ostringstream, and always return a Message&
template<class T>
Message& operator <<(const T &t)
{
(std::ostringstream&)(*this) << t;
return *this;
}
};
Without the template
MyTypeA a,b;
Message m;
m << a << "-" << b;
the code would not compile, as (m << a << "-") would return a ostringstream& which would not be able to take 'b'. So I use the template to make sure to always return a Message&.
My Problem:
Message m;
m << "Hello, world" << std::endl;
generates a veeery long compiler error and I do not know why.
Here is a minimalistic "not" compilable example of my problem, and here is the corresponding compiler output.
Do not derive from any of the stream classes to create a new stream! The only reason to derive from std::ostream or std::istream is to create a stream properly set up to use a suitable stream buffer. Instead of deriving from a stream, you should derive from std::streambuf to create a new source or destination. To create output operators for new types you'd overload operator<<() with std::ostream& as first argument and your custom type as second argument. Likewise with std::istream&.
BTW, the problem you encountered is because std::endl is a function template. Trying to pass a function template somewhere requires that the appropriate instantiation can be deduced. Since your output operators don't cover a suitable signature, the instantiation of std::endl can't be deduced. I could state what's needed but that would be pointless as it is the wrong way to go anyway.
Here is how to make your code compile: http://pastebin.com/xAt5junf
The relevant excerpt:
class Message : public ostringstream
{
public:
Message() {};
virtual ~Message() {};
};
ostream& operator <<(ostream &os, const MyTypeA &a) {
return os << a.getStr();
};
ostream& operator <<(ostream &os, const MyTypeB &b) {
return os << b.getStr();
};
I have a function in my namespace ns that helps me print STL containers. For example:
template <typename T>
std::ostream& operator<<(std::ostream& stream, const std::set<T>& set)
{
stream << "{";
bool first = true;
for (const T& item : set)
{
if (!first)
stream << ", ";
else
first = false;
stream << item;
}
stream << "}";
return stream;
}
This works great for printing with operator << directly:
std::set<std::string> x = { "1", "2", "3", "4" };
std::cout << x << std::endl;
However, using boost::format is impossible:
std::set<std::string> x = { "1", "2", "3", "4" };
boost::format("%1%") % x;
The problem is fairly obvious: Boost has no idea that I would like it to use my custom operator << to print types which have nothing to do with my namespace. Outside of adding a using declaration into boost/format/feed_args.hpp, is there a convenient way to make boost::format look for my operator <<?
The solution I actually went with is quite similar to Answeror's, but it works for anything:
namespace ns
{
template <typename T>
class FormatWrapper
{
public:
explicit FormatWrapper(const T& x) :
ref(x)
{ }
friend std::ostream& operator<<(std::ostream& stream,
const FormatWrapper<T>& self
)
{
// The key is that operator<< is name lookup occurs inside of `ns`:
return stream << self.ref;
}
private:
const T& ref;
};
template <typename T>
FormatWrapper<T> Formatable(const T& x)
{
return FormatWrapper<T>(x);
}
}
So usage is:
boost::format("%1%") % Formatable(x);
I think the most clean way is to provide a thin wrapper in your own namespace for each of the operators you want to override. For your case, it can be:
namespace ns
{
namespace wrappers
{
template<class T>
struct out
{
const std::set<T> &set;
out(const std::set<T> &set) : set(set) {}
friend std::ostream& operator<<(std::ostream& stream, const out &o)
{
stream << "{";
bool first = true;
for (const T& item : o.set)
{
if (!first)
stream << ", ";
else
first = false;
stream << item;
}
stream << "}";
return stream;
}
};
}
template<class T>
wrappers::out<T> out(const std::set<T> &set)
{
return wrappers::out<T>(set);
}
}
Then use it like this:
std::cout << boost::format("%1%") % ns::out(x);
You can try something like this:
namespace boost // or __gnu_cxx
{
using np::operator<<;
}
#include <boost/format/feed_args.hpp>
The problem as already noted is because of ADL (argument dependent lookup - often attributed to Andrew Koenig, but I believe he shouldn't get all the blame).
Even in your local context it wouldn't work in a template function where you intend to use your operator<<.
One cheating trick is to put the operator<< you define into namespace std. That is verboten, but it might work in your case, but only if it is put before its usage and that might be the problem.
There might be further options, such as defining your own Set template. I experimented with
template<typename T> using Set=std::set<T>;
but couldn't get a solution that worked without the
using np::operator<<;
yuyoyuppe provided.
The following won't compile for me. I'm out of ideas... Any help?
template<>
inline
std::ostream& operator<< <const std::map<std::string, std::string> > (std::ostream& stream, const std::map<std::string, std::string>& some_map)
{
return stream;
}
g++ gives me the following error:
error: expected initializer before '<' token
Edit: 1
Okay, since everyone is telling me to overload, let me give you an example that wouldn't make sense for overloading. What if I have this:
template <typename T>
inline
std::ostream& operator<<(std::ostream& stream, const T& something)
{
stream << something.toString();
return stream;
}
class Foo
{
public:
Foo(std::string s)
{
name = s;
}
std::string toString() const
{
return name;
}
private:
std::string name;
};
class Bar
{
public:
Bar(int i)
{
val = i;
}
std::string toString() const
{
std::ostringstream stream;
stream << val;
return stream.str();
}
private:
int val;
};
int main(int, char**)
{
Foo foo("hey");
Bar bar(2);
std::cout << foo << std::endl;
std::cout << bar << std::endl;
return 0;
}
Now this won't work either.
I just want to avoid having to overload operator<< over and over by using a template like above. This seems like it should be possible. I would like to know if it is, and if so, how?
In such a scenario, overloading for both Foo and Bar to do the same thing would be a waste, that is why I am trying to avoid it.
Edit: 2
Okay, it appears that I am being misunderstood. Here is another attempt to clarify:
template <typename T>
std::ostream& operator<<(ostream& stream, const T& t)
{
for(typename T::const_iterator i = t.begin(), end = t.end(); i != end; ++i)
{
stream << *i;
}
return stream;
}
int main(int, char**)
{
set<int> foo;
list<string> bar;
vector<double> baz;
cout << foo << " " bar << " " << baz << endl;
};
The above code won't work mind you. Complains about ambiguity. But it seems like the better solution for printing out containers. If I did it the with overloading, I would need to write a version of operator<< for each container/datatype combination, which would yield a ridiculous amount of code duplication.
This doesn't need to be a template function.
std::ostream & operator<<(std::ostream & stream, const std::map<std::string, std::string> & some_map)
{
return stream;
}
Edit:
In reference to my comment about writing Java in C++(and sorry if it sounded rude, I didn't intend to be smarmy). Tell me if this doesn't work better for you. Instead of writing a "toString" method in the first place, just overload the operator<< to begin with. The function is nearly identical. Then, you can write a non-member template toString function that will automatically work with all of your classes, like this:
#include <sstream>
#include <string>
template<typename T>
std::string toString(const T & val)
{
std::ostringstream ostr;
ostr << val;
return ostr.str();
}
Edit 2
Here's my alternative if you still insist on doing it your way. Make all of your classes with the toString method inherit from an abstract class with a virtual toString method, then write one operator<< to handle all of them.
class Stringifiable
{
public:
virtual std::string toString() const = 0;
};
std::ostream & operator<<(std::ostream & ostr, const Stringifiable& something)
{
return ostr << something.toString();
}
Now the compiler will choose your overload over templates.
You can use SFINAE to remove the template overload from consideration. Note that this has to be a part of the signature of the function. Thus you can use boost::enable_if:
template < typename T >
typename boost::enable_if< meta_function_to_check_for_concept<T>, std::ostream&>::type
operator << (std::ostream & out, T const& t)
{
...
}
If you don't do this then your template will attempt to match almost anything and will explode for every use of << that is not in line with the concept you're trying to match.
Your example is a bit contrived and might not lend itself to this answer, but there are situations in which it's warranted. This is how to do it.
In Crazy Eddie's answer, he mentions SFINAE. Now, C++11 has that built in. If all types derive from the same base class, this is made pretty simple. Here's a more complete example using C++11:
#include <type_traits>
#include <iostream>
#include <ostream>
class MyBaseType {};
class MyClass : MyBaseType {};
class MyOtherClass : MyBaseType {};
class SomeType {};
template <typename T>
typename std::enable_if<std::is_base_of<MyBaseType,T>::value,std::ostream&>::type
operator<<(std::ostream& out, const T& x)
{
out << 1;
}
int main()
{
MyBaseType x;
MyClass y;
MyOtherClass z;
SomeType i;
std::cout << x << y << z; // success!
std::cout << i; // compile-time failure!
}