模板推论不适用于std :: endl吗?

时间:2018-07-05 11:53:16

标签: c++ templates stl

我想将cerr和cout包装在一个对象中,该对象有意丢弃发行版本中的所有内容。目的是确保开发人员可能忘记删除的某些调试输出不会显示给用户。

class Wrapper {
public:
    Wrapper( std::ostream& os ):mOs(os){}

    template <typename T>
    DebugOnlyOsWrapper&
    operator<<( T&& in ){
        #ifndef NDEBUG
            mOs << std::forward<T>(in);
        #endif
        return *this;           
    }

private:
    std::ostream& mOs;
};


extern DebugOnlyOsWrapper dcout;   
extern DebugOnlyOsWrapper dcerr;

但是,按如下所示调用运算符时出现“无法推断出模板参数'T'”错误:

dcerr << std::endl;

我在做什么错?无法从函数指针推断类型吗?

请注意,添加以下运算符可解决此问题,但是我想限制代码重复并了解问题的性质。

using CharT = std::ostream::char_type;   
using Traits = std::ostream::traits_type;

Wrapper& operator<<(std::ios_base& (*func)(std::ios_base&) ){
    #ifndef NDEBUG
        mOs << func;
    #endif
    return *this;           
}
Wrapper& operator<<(
        std::basic_ios<CharT,Traits>& 
            (*func)(std::basic_ios<CharT,Traits>&) 
){
    #ifndef NDEBUG
        mOs << func;
    #endif
    return *this;           
}
Wrapper& operator<<(
        std::basic_ostream<CharT,Traits>& 
            (*func)(std::basic_ostream<CharT,Traits>&) 
){
    #ifndef NDEBUG
        mOs << func;
    #endif
    return *this;           
}

谢谢

1 个答案:

答案 0 :(得分:0)

问题在于std::endl不是函数而是模板。

如果存在以下重载,则在此重载的调用中推导std :: endl的模板,因此它可以工作。

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

另一方面,通用模板没有足够的信息来解析std::endl的模板参数。

因此,最后,我决定使用类似以下的内容:

class Wrapper {
public:
    Wrapper( std::ostream& os ):mOs(os){}

    using CharT = std::ostream::char_type;
    using Traits = std::ostream::traits_type;

    template <typename T>
    Wrapper&
    operator<<( T&& in ){
        return impl(std::forward<T>(in));
    }

    DebugOnlyOsWrapper& operator<<(
            std::basic_ostream<CharT,Traits>& 
                (*func)(std::basic_ostream<CharT,Traits>&) 
    ){
        return impl(func);
    }

private:
    template <typename T>
    DebugOnlyOsWrapper& impl( T&& in ){
        #ifndef NDEBUG
            mOs << std::forward<T>(in);
        #endif
        return *this;           
    }
    std::ostream& mOs;
};