虚拟调试类停留在std :: endl重载

时间:2017-05-15 19:56:17

标签: c++ debugging c++14 conditional-compilation

我以为我会用这样的事情做一个快速而肮脏的__DEBUG启用跟踪:

#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;
}

但它给了我:

cond_dbg.cpp:16:66: error: decltype cannot resolve address of overloaded function
  dummy_cout & operator << ( std::result_of< decltype( &std::endl ) >::type &obj )

我还尝试了decltyperesult_ofostream等六种变体,但我还没有采取任何进一步措施。

这很简单。如果我编译定义__DEBUG的代码,我会coutcerr。如果我进行正常的编译,我会得到dummy_cout,它只会做什么,但只允许我的代码编译而不会有任何变化和杂乱。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

你不能写decltype(&std::endl),因为std::endl不是函数,它是函数模板

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& endl( std::basic_ostream<CharT, Traits>& os );

因此,它没有类型,所以要求它没有意义。而且,即使它确实有类型,随后的result_of包装也没有任何意义。

std::cout << std::endl有效的原因是有overload接受特定类型的函数指针:

basic_ostream& operator<<(
    std::basic_ios<CharT,Traits>& (*func)(std::basic_ios<CharT,Traits>&) );

此运算符不是函数模板(它是basic_ostream的成员函数,它是一个类模板),因此重载解析会触发endl特化的实例化。

要实现这一点,您应该做同样的事情:

dummy_cout& operator<<( std::ostream&(*p)(std::ostream&) );

或为您的虚拟类型选择一些合适的CharTTraits

dummy_cout& operator<<( std::basic_ostream<C,T>&(*p)(std::basic_ostream<C,T>& ) );

请注意。这个声明在任何C ++标准中都是错误的:

dummy_cout& operator<<(auto& obj);

Terse函数模板语法是Concepts TS的一个特性,它仍然是TS。除非你使用 - fconcepts,否则你需要写:

template <class T>
dummy_cout& operator<<(T& obj);