Оберните ostream в классе и шаблонизируйте << оператор - PullRequest
0 голосов
/ 13 сентября 2018

Я хочу обернуть потоки C ++ в класс шаблона так, чтобы все операции <<, определенные для потоков, уже были доступны для класса оболочки. </p>

Можно ли изменить следующий код так, чтобы он компилировался безслишком много изменили общее намерение?

#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 имеет некоторый тип и, следовательно, "перехватывается" шаблонным методом.

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Вы, вероятно, должны защищать его с помощью SFINAE и безупречно пересылать аргумент.

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

Теперь это должно принять каждый аргумент std::ostream может вывести и не скомпилироваться со всем остальным.

0 голосов
/ 13 сентября 2018

Как рекомендует 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;
    }
};
...