Modern pattern to write custom ostream operator - c++11

Typically, in C++, we used to define a custom ostream operator<< this way:
class A {
int impl_;
friend std::ostream& operator<<(std::ostream& os, A const& self){
return os << "A:" << self.impl_;
}
};
However now, post C++11, there are r-value references, and as a matter of fact, built-in types can be streamed to r-value std::ostream references.
Now this is allowed:
int i = 5;
std::ofstream("file") << i;
(I don't know if this is the reason the special overloads were defined.)
Does it mean that for consistency one should define both operators for custom classes? Like this,
class A {
int impl_;
friend std::ostream& operator<<(std::ostream& os, A const& self) {
return os << "A:" << self.impl_;
}
friend std::ostream&& operator<<(std::ostream&& os, A const& self) {
os << "A:" << self.impl_;
return std::move(os);
}
};
or more streamlined,
class A {
int impl_;
friend std::ostream& operator<<(std::ostream& os, A const& self) {
return os << "A:" << self.impl_;
}
friend std::ostream&& operator<<(std::ostream&& os, A const& self) {
return std::move(os << self); // calls the other overload
}
};
What is the recommended way to overload operator<< nowadays in C++11?

Besides the conceptual discussion, from a technical viewpoint:
After some experimentation I realized that I don't need to overload for the r-value ostream, the library does it for me already.
One only has to have the l-value version and the library has some r-value version that is forwarded to the implemented overload, which presumably works for any std namespace argument of operator << through ADL or something.
So, in C++11, this is allowed std::ofstream{"file"} << a, even if no r-value overload (for the stream) is custom defined.
Which seems to make operator<< quite special in STL.
Corrections are welcome.

Related

Undefined reference to friend function template defined inside class in a namespace

This is a follow-up on my answer to this question.
The original answer I posted does not have any namespaces, and it solves the problem. However, the OP subsequently made an edit claiming that the solution does not work if the class is inside a namespace.
My initial reaction was that you can make it work by simply having using N::f; either at global scope or inside main() (or any other function). While that is certainly the case, the OP (justifiably) commented that this is not ideal, and I agree.
Nevertheless, I still thought that calling N::f without having using N::f; should work just fine, but to my surprise I got an undefined reference error when I tried the following:
#include<iostream>
namespace N
{
template<class T>
class Class;
template<typename U, typename W>
Class<W> f (Class<U>& C, const Class<U>& D);
template<class T>
class Class
{
protected: // this could be private
T m_t;
public:
Class()
:
m_t(T())
{}
Class(T t)
:
m_t(t)
{}
T& getT()
{
return m_t;
}
template<typename U, typename W>
friend Class<W> f (Class<T>& C, const Class<T>& D)
{
C.m_t += D.m_t;
Class<W> R;
std::cout << R.m_t << std::endl; // I don't want this to be possible
return R;
}
};
}
int main()
{
N::Class<int> C(42), D(24);
std::cout << N::f<int, char>(C, D).getT() << std::endl;
}
error: undefined reference to N::Class<char> N::f<int, char>(N::Class<int>&, N::Class<int> const&)'.
At this point, I went on to try different compiler versions and discovered that the above works as it does without a namespace with GCC < 6 but not with GCC > 6. ICC 17 also seems to pick up on the protected member access inside f, but not ICC 18. Clang never picks it up.
Which is the intended behaviour? Should the definition be made available to the linker in this case without using N::f;?.
Edit 1:
To clarify, I want to retain the intended behaviour, namely restricting f to be a friend only to Class instantiations that match its arguments (so in the example f would be friend to Class<T> but not to Class<W>).

Why reference_wrapper behaves differently for built-in types?

I have the following use of std::reference_wrapper for a build in type (double) and for a user defined type (std::string).
Why do they behave differently in the case of the stream operator?
#include<functional> //reference wrapper
#include<iostream>
void fd(double& d){}
void fs(std::string& s){}
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
std::cout << "DR = " << DR << std::endl; //ok
fd(DR); // ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
std::cout << "SR = " << static_cast<std::string&>(SR) << std::endl; // ok
std::cout << "SR = " << SR << std::endl; // error: invalid operands to binary expression ('basic_ostream<char, std::char_traits<char> >' and 'std::reference_wrapper<std::string>')
fs(SR); // ok
}
http://coliru.stacked-crooked.com/a/fc4c614d6b7da690
Why in the first case DR is converted to double and printed and in the second it is not? Is there a work around?
Ok, I see now, in the ostream case I was trying to called a templated function that is not resolved:
#include<functional> //reference wrapper
void double_fun(double const& t){};
template<class C>
void string_fun(std::basic_string<C> const& t){};
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
double_fun(DR); //ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
string_fun(SR); // error: no matching function for call to 'string_fun'
string_fun(SR.get()); // ok
string_fun(static_cast<std::string&>(SR)); // ok
string_fun(*&SR); // would be ok if `std::reference_wrapper` was designed/coded differently, see http://stackoverflow.com/a/34144470/225186
}
For the first part TC gave you the answer. That is, operator<< for basic_string is templated, and template argument deduction doesn't look through implicit conversions.
You could alternatively call SR.get() if you don't want to explicitly to static_cast your reference wrapper.
Now for the second part, string_fun takes as input arguments std::basic_string<C> objects. When you call:
string_fun(SR);
with SR as input parameter which is of type std::reference_wrapper<std::string>, naturally you get a type mismatch.
What you can do is provide an additional overload:
template<class C>
void string_fun(std::reference_wrapper<std::basic_string<C>> const& t) {
};
Live Demo
Or if you want a more unified treatment you could define your string_fun to take template template arguments, and resolve the type with some kind of type trait magic like bellow:
template<template<typename...> class C, typename T>
void
string_fun(C<T> const &t) {
std::cout <<
static_cast<std::conditional_t<
std::is_same<
std::reference_wrapper<T>, C<T>>::value, T, std::basic_string<T>>>(t) << std::endl;
}
Live Demo

How to store functional objects with different signatures in modern C++

I would like to know if there is a way to store functional objects (functions, callbacks, ...) with different signatures in a standard container (std::map) with modern C++ only. The library that manages the container does not know which signatures will be used by its "clients".
My need is the same as exposed here : How to store functional objects with different signatures in a container?, and this solution https://stackoverflow.com/a/8304873/4042960 is about perfect for me: I would just like to do the same thing without boost. As far as I know, there is no std::any. The best solution for me would be to store std::function without specialized them, but I do not know how to do it, if it is possible.
Edit:
With the answers you give to me I wrote this example :
#include <map>
#include <memory>
#include <functional>
#include <string>
#include <iostream>
#include <stdexcept>
class FunctionMap
{
struct Base {
virtual ~Base() {}
};
template<class R, class... Args>
struct Func : Base
{
std::function<R(Args...)> f;
};
std::map<std::string, std::shared_ptr<Base> > _map;
public:
template<class R, class... Args>
void store(const std::string &key, const std::function<R(Args...)> &f) {
auto pfunc = std::make_shared<Func<R, Args...> >();
pfunc->f = f;
_map.insert(std::make_pair(key, pfunc));
}
template<class R, class... Args>
std::function<R(Args...)> get(const std::string &key) {
auto pfunc = std::dynamic_pointer_cast<Func<R, Args...> >(_map[key]);
if (pfunc)
return pfunc->f;
else
throw std::runtime_error("Bad type for function's parameters");
}
};
// test
int plus(int a, int b) { return a+b; }
double multiplies(double x, double y) { return x*y; }
int main()
{
FunctionMap fm;
fm.store("plus", std::function<int(int, int)>(&plus));
fm.store("multiplies", std::function<double(double, double)>(&multiplies));
// fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1));
std::cout << "5 + 3 = " << fm.get<int, int, int>("plus")(5, 3) << std::endl;
std::cout << "5 * 3 = " << fm.get<double, double, double>("multiplies")(5.0, 3.0) << std::endl;
return 0;
}
This works well, but I would like to improve it a bit:
1) I would like to be able to use std::bind : fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1)); but currently that does not compile ;
2) I would like to use fm.get<int (int, int)>("plus") instead of fm.get<int, int, int>("plus") but I do not know how to do it.
Many thanks for your help !
You can write your own any. Without all the compiler workarounds and stuff, boost::any can be written in about 30 lines of code.
Function objects are in no way different from any other kind of objects, so anything applicable to objects in general is applicable to function objects.
So you want to store different kinds of (function) objects in a map. This is normally done by storing (smart) pointers to a base class, where each derived class holds its own kind of objects you want to store.
struct Base {
virtual ~Base(){}
};
template <typename A>
struct Object : Base {
A value;
};
That's your basic caveman's boost::any. Your clients do something like this:
Base* b = mymap["foo"];
dynamic_cast<Object<void(*)(int)>*>(b)->val(123);
But with appropriate checks of course.

Output to logging class via operator<<

I have implemented a logging class TLogFile and now I want to overload the output operator<<.
I want to use the log like this:
TLogFile* log = new TLogFile("some arguments...");
*log << "Hello world."; // (1)
*log << "Hello world." << endl; // (2)
*log << std::hex << setw(2) << setfill('0') << someValue << endl; // (3)
I used ostream as a class member and as a friend. The class looks like this:
namespace app {
class TLogFile
{
public:
app::TLogFile& operator<< (std::string& out);
std::ostream& operator<< (std::ostream& out);
friend std::ostream& operator<< (std::ostream& out, TLogFile& o);
};
} // namespace app
Only plain text (1) is working by using the string version. A soon as I use endl (2) or iomanip (3) I get error messages:
../src/main.cpp:164:70: error: no match for 'operator<<' in 'sysdat.app::cSystemData::obj.app::cSystemObjects::applicationLog->app::TLogFile::operator<<((* & std::basic_string(((const char*)"sysdat.obj.applicationLog <<"), ((const std::allocator*)(& std::allocator()))))) << std::endl'
../src/main.cpp:164:70: note: candidates are:
../src/inc/logger.h:85:17: note: app::TLogFile& app::TLogFile::operator<<(const string&)
../src/inc/logger.h:85:17: note: no known conversion for argument 1 from '' to 'const string& {aka const std::basic_string&}'
../src/inc/logger.h:88:17: note: std::ostream& app::TLogFile::operator<<(std::ostream&)
../src/inc/logger.h:88:17: note: no known conversion for argument 1 from '' to 'std::ostream& {aka std::basic_ostream&}'
../src/inc/logger.h:93:23: note: std::ostream& app::operator<<(std::ostream&, app::TLogFile&)
../src/inc/logger.h:93:23: note: no known conversion for argument 1 from 'app::TLogFile' to 'std::ostream& {aka std::basic_ostream&}'
I believed that one of the ostream version should work.
Has anyone an idea how to overload the operator so that endl and iomanip can be used?
Your operator<< is able to take only std::ostream& and std::string&
(note: probably it should be const std::string&).
The most elegant solution I can imagine is to write a template:
class TLogFile{
protected:
std::ostream* stream;
public:
/* default ctor, copy ctor and assignment operator: */
TLogFile(std::ostream& _stream=std::clog):stream(&_stream){}
TLogFile (const TLogFile&) =default;
TLogFile& operator= (const TLogFile&) =default;
/* std::endl is overloaded,
* so I think compiler doesn't know which version to use.
* This funchtion handles function pointers, including std::endl
*/
inline TLogFile& operator<< (std::ostream&(*func)(std::ostream&)){
(*stream) << func;
return *this;
}
/* should handle everything else */
template<typename T>
inline TLogFile& operator<< (const T& t) {
(*stream) << t;
return *this;
}
}
See it working in online compiler
This way your objects' operator<<s should be able to take anything that std::ostream's can take.
Edit:
Next time, please say that you want to have custom std::endl.
I'm not sure that function with signature
inline TLogFile& operator<< (std::ostream&(*func)(std::ostream&))
is used only when std::endl is passed to it. My previous solution seems inelegent or even inworking. I'm wondering about how to change behaviour of std::endl when it's passed to object of different class.
Notes:
In most cases I'd like to use '\n instead of std::endl.
TLogFile* log = new TLogFile("some arguments...");
I think using raw pointer isn't the best idea here (it's easy to forget about delete),
unless you have to explicitly decide when the object should die.
When the object should die when the current scope does, it should be a local variable:
TLogFile log("some arguments...");
//Usage:
log << "Hello world."; // (1)
log << "Hello world." << endl; // (2)
log << std::hex << setw(2) << setfill('0') << someValue << endl; // (3)
If the object is used in multiple places, and each of the places uses it independently from others, IMO the best solution is to use std::shared_ptr:
#include <memory>
#include <utility>
auto log=std::make_shared<TLogFile>("some arguments...");
//Usage:
*log << "Hello world."; // (1)
*log << "Hello world." << endl; // (2)
*log << std::hex << setw(2) << setfill('0') << someValue << endl; // (3)
This way the object dies when the last shared_ptr does.
I used pointer in the class to be able to re-assign it. If you don't need re-assignment, you can use reference instead.
Thanks to GingerPlusPlus. I found out, that the operator operator<< (std::ostream&(*func)(std::ostream&)) is called only once for the endl (maybe this assumtion is not always true, Please read remarks/edit above of GingerPlusPlus). I replaced the ostream against a stringstream and write the contens of the stringstream when the operator ist called.
class TLogFile{
protected:
std::ostream* stream;
std::stringstream line;
public:
/* default ctor, copy ctor and assignment operator: */
TLogFile(std::ostream& _stream=std::clog):stream(&_stream){}
TLogFile (const TLogFile&) =default;
TLogFile& operator= (const TLogFile&) =default;
void write() {
// Doing some write stuff
// ...
// Empty stringstream buffer
line.str(std::string());
}
/* std::endl is overloaded,
* so I think compiler doesn't know which version to use.
* This funchtion handles function pointers, including std::endl
*/
inline TLogFile& operator<< (std::ostream&(*func)(std::ostream&)){
line << func;
write();
return *this;
}
/* should handle everything else */
template<typename T>
inline TLogFile& operator<< (const T& t) {
line << t;
return *this;
}
}

Recursive printing of tuple in C++

There are several proposals on how to print a tuple. The snippet below reproduces the answer of Kenny from overloading operator << for std::tuple - possible simplications?.
#include <iostream>
#include <tuple>
#include <type_traits>
// template <typename... T>
// std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& tup);
template <size_t n, typename... T>
typename std::enable_if<(n >= sizeof...(T))>::type
print_tuple(std::ostream&, const std::tuple<T...>&)
{}
template <size_t n, typename... T>
typename std::enable_if<(n < sizeof...(T))>::type
print_tuple(std::ostream& os, const std::tuple<T...>& tup)
{
if (n != 0)
os << ", ";
os << std::get<n>(tup);
print_tuple<n+1>(os, tup);
}
template <typename... T>
std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& tup)
{
os << "[";
print_tuple<0>(os, tup);
return os << "]";
}
int
main()
{
auto t = std::make_tuple(1, std::make_tuple(2, 3));
std::cout << t << std::endl;
}
My problem is that it does not work properly with clang (3.5) with tuples of tuples (gcc 4.9 is happy though):
clang++-mp-3.5 -std=c++11 print.cc
print.cc:19:10: error: call to function 'operator<<' that is neither visible in the
template definition nor found by argument-dependent lookup
os << std::get<n>(tup);
^
print.cc:20:7: note: in instantiation of function template specialization
'print_tuple<1, int, std::__1::tuple<int, int> >' requested here
print_tuple<n+1>(os, tup);
^
print.cc:27:7: note: in instantiation of function template specialization
'print_tuple<0, int, std::__1::tuple<int, int> >' requested here
print_tuple<0>(os, tup);
^
print.cc:35:19: note: in instantiation of function template specialization
'operator<<<int, std::__1::tuple<int, int> >' requested here
std::cout << t << std::endl;
^
print.cc:24:19: note: 'operator<<' should be declared prior to the call site
std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& tup)
^
If I uncomment the forward declaration for operator<< on tuples, it works. However it does not fit nicely in a framework where you don't force the definition of operator<< for tuples, but leave to the user the choice to bind it to print_tuple: she has to forward declare the function before including the header that defines print_tuple.
I don't understand well what's going on here: in a template, clang appears to refuse to use functions that are defined after the point of the definition of the template, but before the point of instantiation. I would have thought that what matters is the point of instantiation.
Conversely, why does GCC accept? Is one of the compilers wrong? What would be the nicest way to leave to the user the choice of defining this operator<<, and have it work properly recursively?
Thanks.
You can read about the reason clang is not compiling it here: http://clang.llvm.org/compatibility.html#dep_lookup . It seems that clang's behaviour is standard-compliant.
To fix it, you can define operator<< in namespace std to make argument-dependent lookup work correctly. Actually this might be undefined behaviour, since it does not comply with the requirements for adding stuff to std.

Resources