Реализация no-op std :: ostream

Вы можете использовать такой код:

char *MyFunction(some arguments...)
{
    char *pointer = malloc(size for the new array);
    if (!pointer)
        An error occurred, abort or do something about the error.
    return pointer; // Return address of memory to the caller.
}

Когда вы это сделаете, память должна быть освобождена позже, передав адрес бесплатно.

Есть другие варианты , Подпрограмма может возвращать указатель на массив (или часть массива), который является частью некоторой существующей структуры. Вызывающий может передать массив, и программа просто записывает в массив, а не выделяет пространство для нового массива.

30
задан jcs 17 April 2009 в 13:08
поделиться

5 ответов

Чтобы предотвратить вызовы оператора << () от выполнения форматирования вы должны знать тип потока во время компиляции. Это можно сделать либо с помощью макросов, либо с помощью шаблонов.

Мое шаблонное решение следует.

class NullStream {
public:
    void setFile() { /* no-op */ }
    template<typename TPrintable>
    NullStream& operator<<(TPrintable const&)
    { return *this; } /* no-op */
}

template<class TErrorStream> // add TInfoStream etc
class Logger {
public:
    TErrorStream& errorStream() {
        return m_errorStream;
    }

private:
    TErrorStream m_errorStream;
};

//usage
int main() {
    Logger<std::ofstream> normal_logger; // does real output
    normal_logger.errorStream().open("out.txt");
    normal_logger.errorStream() << "My age is " << 19;

    Logger<NullStream> null_logger; // does zero output with zero overhead
    null_logger.errorStream().open("out.txt"); // no-op
    null_logger.errorStream() << "My age is " << 19; // no-op
}

Поскольку вы должны делать это во время компиляции, оно, конечно, довольно негибко.

Например, вы не можете решить Уровень ведения журнала во время выполнения из файла конфигурации.

4
ответ дан 27 November 2019 в 21:10
поделиться

Быстрый Google придумала этот пример, который может быть полезен. Я не даю никаких гарантий, за исключением того, что он компилируется и запускается: -)

#include <streambuf>
#include <ostream>

template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
    typename traits::int_type overflow(typename traits::int_type c)
    {
        return traits::not_eof(c); // indicate success
    }
};

template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
    public:
        basic_onullstream():
        std::basic_ios<cT, traits>(&m_sbuf),
        std::basic_ostream<cT, traits>(&m_sbuf)
        {
            init(&m_sbuf);
        }

    private:
        basic_nullbuf<cT, traits> m_sbuf;
};

typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;

int main() {
    onullstream os;
    os << 666;
}
16
ответ дан 27 November 2019 в 21:10
поделиться

Почему бы не использовать существующие решения для ведения журналов? миллионами пользователей? log4j, log4net, log4cxx .., и это лишь некоторые из них.

0
ответ дан 27 November 2019 в 21:10
поделиться

Возможно, вам понадобится больше, чем просто форматирование текста и фильтрация сообщений. Как насчет многопоточности?

Я бы реализовал фильтрацию и синхронизацию многопоточности как ответственность отдельного класса.

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

0
ответ дан 27 November 2019 в 21:10
поделиться

все, спасибо за то, что поделились кодом, я просто провожу тест, тогда метод Нила все равно будет формировать строку, например:

#include <streambuf>
#include <ostream>
#include <iostream>
using namespace std;


template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
    typename traits::int_type overflow(typename traits::int_type c)
    {
        return traits::not_eof(c); // indicate success
    }
};

template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
    public:
        basic_onullstream():
        std::basic_ios<cT, traits>(&m_sbuf),
        std::basic_ostream<cT, traits>(&m_sbuf)
        {
            init(&m_sbuf);
        }

    private:
        basic_nullbuf<cT, traits> m_sbuf;
};

typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;

class MyClass
{
    int a;
    friend ostream& operator<< (ostream&, MyClass const&);
};

ostream& operator<<(ostream& out,MyClass const& b)
{
    std::cout<<"call format function!!";
    out << b.a;
    return out;
}

int main() {
    onullstream os;
    MyClass obj;
    os<<obj;
}

Запустив эту программу, вы обнаружите, что "ostream & operator << (ostream & out, MyClass const & b) ". Таким образом, выполнение форматирования для объекта по-прежнему будет вызываться. Таким образом, мы по-прежнему не можем избежать накладных расходов на форматирование сообщений.

13
ответ дан 27 November 2019 в 21:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: