当转发到std :: ostream <<时,机械手的模板参数推导失败

时间:2019-03-30 09:13:50

标签: c++

尝试继承std::ostream并使用自定义operator <<时遇到了一些麻烦,该自定义std::ostream <<基本上是在做一些工作,然后转发到#include <iostream> #include <ostream> struct ostream : std::ostream{ using std::ostream::ostream; template<typename T> ostream &operator <<(T &&arg){ //some work... static_cast<std::ostream&>(*this) << std::forward<T>(arg); return *this; } }; int main(){ ostream cc(std::cout.rdbuf()); cc << "hello world"; //cc << "hello world" << std::endl; //couldn't deduce template parameter `T` } ,例如:

std::ostream::operator <<

问题是使用操纵器时,就像我注释掉的那一行一样,gcc抱怨[模板参数推导/替换失败:]。

我是否必须显式设置模板类型?如果可以,如何设置?,因为由于不完整而无法使用in类operator <<

Live on Wandbox


编辑

我刚刚将自定义ostream定义为自由函数,因此没有在类#include <iostream> #include <ostream> struct ostream : std::ostream{ using std::ostream::ostream; }; template<typename T> ostream &operator <<(ostream &os, T &&arg) { static_cast<std::ostream&>(os) << std::forward<T>(arg); return os; } int main(){ ostream cc(std::cout.rdbuf()); cc << "hello world" << std::endl; }

{{1}}

,它对于机械手也按预期工作。不知道为什么这会有所作为,也许有人可以帮我澄清一下

1 个答案:

答案 0 :(得分:2)

问题是操纵器是模板化的,并且您的类没有提供为std::endl选择正确的模板参数所需的信息。您应该为操纵器重载operator<<

struct ostream : std::ostream{
    using std::ostream::ostream;

    template<typename T>
    ostream &operator <<(T &&arg){
        //some work...
        static_cast<std::ostream&>(*this) << std::forward<T>(arg);
        return *this;
    }
    ostream &operator<<(
      std::ostream &(*manip)(std::ostream&)) {
              //some work...
        static_cast<std::ostream&>(*this) <<manip;
        return *this;
    }
};

请注意,问题中的代码由于以下原因而失败:

auto manip = std::endl;

它根本无法推论endl的模板参数。

更新

使ovloading成为自由函数的替代方法并没有实现人们的期望:

template<typename T>
ostream &operator <<(ostream &os, T &&arg)
{
    static_cast<std::ostream&>(os) << std::forward<T>(arg);
    return os;
}
int main(){
    ostream cc(std::cout.rdbuf());
    cc << "hello world" << std::endl;
}

获取std::endl的运算符来自原始的iostream库。在这种情况下,编译器不会执行重载函数,因此没有编译错误。

如果您不想使操纵器过载,则可以显式提供模板参数:

cc << "hello world" << std::endl<char, std::char_traits<char>>;