【问题标题】:Wrap ostream in class and templatize << operator在类中包装 ostream 并模板化 << 运算符
【发布时间】:2018-09-13 08:25:55
【问题描述】:

我想将 C++ 流包装在模板类中,以便为流定义的所有

您能否更改以下代码,使其在不过多改变整体意图的情况下进行编译?

#include <iostream>
class Foo
{
private:

    std::ostream& os;

public:

    explicit Foo( std::ostream& os ) : os( os ) {};

    template<class T>
    Foo& operator<<( const T& t )
    {
        os << t << '!';
        return *this;
    }

};

int main()
{

    Foo( std::cout ) << "test" << '\n'; // works fine 
    Foo( std::cout ) << "test" << std::endl; // compilation error

    return 0;
}

我假设 std::endl 具有某种类型,因此被模板化方法“捕获”。

【问题讨论】:

  • std::endl 是一个模板函数,因此它的类型不能由它自己推断。 Streams 有一个 overload 用于该形式的函数,以帮助进行类型推断。
  • This thread 应该会有所帮助。上下文有点不同(可变参数包),但答案应该阐明问题是什么以及如何缓解它。
  • 我需要一个实际编译的例子。

标签: c++ c++11 templates iostream


【解决方案1】:

根据 kmdreko 的建议,您需要为模板函数添加重载

(std::endl 是模板函数,不是类或简单类型)

像这样:

#include <iostream>
class Foo
{
private:

    std::ostream& os;

public:

    explicit Foo(std::ostream& os) : os(os) {};

    // for classes
    template<class T>
    Foo& operator<<(const T& t)
    {
        os << t << '!';
        return *this;
    }

    // for endl
    Foo& operator<<(std::ostream& (*pf) (std::ostream&)) {
        os << pf;
        return *this;
    }
};

【讨论】:

    【解决方案2】:

    您可能应该使用 SFINAE 保护它并完善该论点。

        template<class T> auto operator<<(T &&t)
             -> decltype(os << std::forward<T>(t) << '!', *this)
        {
                return os << std::forward<T>(t) << '!', *this;
        }
    

    现在这应该接受每个参数 std::ostream 可以打印并且无法与其他所有参数一起编译。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-17
      • 1970-01-01
      • 2023-01-09
      • 2010-10-07
      • 1970-01-01
      • 2019-09-27
      • 1970-01-01
      相关资源
      最近更新 更多