I thought I was going to do a quick-and-dirty __DEBUG
enabled tracing with something like this:
#ifdef __DEBUG
# define dbg std::cout
# define err std::cerr
#else
#include <iostream>
class dummy_cout
{
private:
public:
dummy_cout & operator << ( auto &obj )
{ return *this; }
dummy_cout & operator << ( std::result_of< decltype( &std::endl ) >::type &obj )
{ return *this; }
};
# define dbg dummy_cout()
# define err dummy_cout()
#endif
int main( int argc, char *argv[] )
{
dbg << "Bla, bla. bla..." << std::endl;
}
But it gives me:
cond_dbg.cpp:16:66: error: decltype cannot resolve address of overloaded function
dummy_cout & operator << ( std::result_of< decltype( &std::endl ) >::type &obj )
I have also tried a half-dozen variations of decltype
, result_of
, ostream
, etc. but I still haven't gotten any step further.
It oughta be simple. If I compile the code defining __DEBUG
, I'd have cout
and cerr
. If I make a normal compilation, I'd have my dummy_cout
, that simply does nothing but allows my code to compile without changes and little clutter.
Any help will be greatly appreciated.
You can't write decltype(&std::endl)
because std::endl
isn't a function, it's a function template:
template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );
As such, it doesn't have a type, so it doesn't make sense to ask for it. Moreover, even if it did have a type, the subsequent result_of
wrapping wouldn't make any sense.
The reason that std::cout << std::endl
works is that there is an overload that accepts a specific type of function pointer:
basic_ostream& operator<<(
std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&) );
This operator is not a function template (it is a member function of basic_ostream
, which is a class template), and so overload resolution here triggers instantiation of a specialization of endl
.
To get this to work, you should just do the same thing:
dummy_cout& operator<<( std::ostream&(*p)(std::ostream&) );
or pick some appropriate CharT
and Traits
for your dummy type:
dummy_cout& operator<<( std::basic_ostream<C,T>&(*p)(std::basic_ostream<C,T>& ) );
Just a note. This declaration is ill-formed any C++ standard:
dummy_cout& operator<<(auto& obj);
Terse function template syntax is a feature of the Concepts TS, which is still a TS. Unless you're using -fconcepts
, you need to write:
template <class T>
dummy_cout& operator<<(T& obj);