Цепочка C ++ оператора ‹< для std :: cout как использование

Возможный дубликат:
std :: endl имеет неизвестный тип при перегрузке оператора ‹<
Перегрузка оператора

В настоящее время я программирую класс регистратора, но метод operator<< вызывает ошибку компилятора. Вот уменьшенная версия класса в файле "logger.h":

#include <iostream>
class Logger {
public:
    Logger() : m_file(std::cout) {}

    template <typename T>
    Logger &operator<<(const T &a) {
        m_file<<a;
        return *this;
    }

protected:
    std::ostream& m_file;
};

Он включен в мой main.cpp и отлично работает при выводе строкового литерала:

log << "hi"; 

Однако следующее не будет компилироваться.

#include "logger.h"
int main() {
    Logger log;

    log << std::endl;
}

Компилятор g ++ сообщает:

src / main.cpp: 5: error: нет совпадения для 'operator ‹*' в 'log ‹* std :: endl'


person Tuxer    schedule 07.12.2011    source источник


Ответы (2)


Ваша проблема не в цепочке из <<, проблема также может возникнуть из-за одного log << endl. Это потому, что std::endl является функцией-шаблоном:

template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);

Одна из перегрузок operator<< в basic_ostream:

template <class charT, class traits = char_traits<charT> >
class basic_ostream : virtual public basic_ios<charT,traits> {
public:
    basic_ostream<charT,traits>& operator<<(
    basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
//...
};

Таким образом, параметры шаблона могут быть выведены при использовании std::cout<<std::endl. Однако, когда левая сторона - это class Logger, компиляция не может вывести параметры шаблона endl. Явно укажите параметры шаблона, чтобы программа могла скомпилироваться и работать:

#include <iostream>
class Logger
{
public:
    std::ostream &m_file;
    Logger(std::ostream &o = std::cout):m_file(o){};

    template <typename T>
    Logger &operator<<(const T &a) {
        m_file<<a;
        return *this;
    }
};

int main()
{
    Logger log;
    log<<std::endl<char, std::char_traits<char> >;
    log<<"hi"<<" stackoverflow"<<std::endl<char, std::char_traits<char> >;
    return 0;
}

Или вы можете добавить новую перегрузку operator<< в class Logger, чтобы компилятор мог определить параметры шаблона std::endl:

#include <iostream>
class Logger
{
public:
    std::ostream &m_file;
    Logger(std::ostream &o = std::cout):m_file(o){};

    template <typename T>
    Logger &operator<<(const T &a) {
        m_file<<a;
        return *this;
    }

    Logger &operator<<(std::ostream& (*pf) (std::ostream&)){
        m_file<<pf;
        return *this;
    }
};

int main()
{
    Logger log;
    log<<std::endl;
    log<<"hi"<<" stackoverflow"<<std::endl;
    return 0;
}

Кроме того, если вам не нужно, чтобы вывод был немедленно сброшен, вы можете использовать '\ n' вместо endl.

person fefe    schedule 07.12.2011
comment
Кроме того, вы можете использовать '\ n' вместо endl. Нет, если OP хочет убедиться, что выходные буферы очищены, как я недавно узнал. - person Some programmer dude; 07.12.2011
comment
Хорошо, я добавлю это к своему ответу. - person fefe; 07.12.2011