【问题标题】:Template deduction does not work with std::endl?模板推导不适用于 std::endl?
【发布时间】:2018-07-05 11:53:16
【问题描述】:

我想将 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;           
}

谢谢

【问题讨论】:

标签: c++ templates stl


【解决方案1】:

问题在于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;
};

【讨论】:

  • 令人着迷。我可以发誓在我建议的问题的答案中给出相同的解释。
  • @StoryTeller 是的,我同意,答案是一样的,但问题与 IMO 不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 2014-01-19
  • 1970-01-01
相关资源
最近更新 更多