2013-02-19 3 views
4

Я хочу создать класс, который поможет мне отлаживать, предоставляя функции std :: cout или QDebug, используя 3D-рендеринг.Оператор перегрузки << для текстового рендеринга

У меня есть следующий метод визуализации, который я использую в настоящее время

IRenderer::renderText(int posX, int posY, const float* color, const char* text, ...); 

// E.g. 
int i; 
float f; 
float color[] = {1, 1, 1, 1}; 

renderer->renderText(50, 50, color, "Float %f followed by int %i", f, i); 

Это на самом деле работает хорошо, но мне интересно, если это возможно, чтобы создать класс, который позволит мне сделать это следующим образом:

debug() << "My variables: " << i << ", " << "f"; 

Я предполагаю, что будет функция шаблона, которая построит строку для перехода к renderText() на основе типа ввода, но я не совсем уверен, как ее реализовать.

ответ

2

Альтернативой ответ Роба будет включать в ваш пользовательский класс регистратора в ostringstream, и использовать деструктор, чтобы сделать регистрацию:

#include <iostream> 
#include <sstream> 

class MyLogger 
{ 
protected: 
    std::ostringstream ss; 

public: 
    ~MyLogger() 
    { 
     std::cout << "Hey ma, I'm a custom logger! " << ss.str(); 

     //renderer->renderText(50, 50, color, ss.str()); 
    } 

    std::ostringstream& Get() 
    { 
     return ss; 
    } 
}; 

int main() 
{ 
    int foo = 12; 
    bool bar = false; 
    std::string baz = "hello world"; 

    MyLogger().Get() << foo << bar << baz << std::endl; 

    // less verbose to use a macro: 
#define MY_LOG() MyLogger().Get() 
    MY_LOG() << baz << bar << foo << std::endl; 

    return 0; 
} 
+0

Вместо использования макросов я предлагаю вам определить 'template MyLogger & operator << (T const &)' для класса MyLogger, который будет делать то же самое с 'ss' – kassak

0

Мне нравится выводить мой класс ведения журнала из std :: ostream, поэтому я получаю все удовольствие от потока. Хитрость заключается в том, чтобы поместить весь ваш прикладной код в соответствующий класс streambuf. Рассмотрим этот рабочий пример. Для того, чтобы изменить его MEED ваши потребности, просто переписать CLogBuf::sync(), например, так:

int sync() { 
    renderer->renderText(50, 50, color, "%s", str()); 
    str(""); 
    return false; 
} 

Пример:

#include <iostream> 
#include <sstream> 

class CLogger : public std::ostream { 
private: 
    class CLogBuf : public std::stringbuf { 
    private: 
     // or whatever you need for your application 
     std::string m_marker; 
    public: 
     CLogBuf(const std::string& marker) : m_marker(marker) { } 
     ~CLogBuf() { pubsync(); } 
     int sync() { std::cout << m_marker << ": " << str(); str(""); return !std::cout; } 
    }; 

public: 
    // Other constructors could specify filename, etc 
    // just remember to pass whatever you need to CLogBuf 
    CLogger(const std::string& marker) : std::ostream(new CLogBuf(marker)) {} 
    ~CLogger() { delete rdbuf(); } 
}; 

int main() 
{ 
    CLogger hi("hello"); 
    CLogger bye("goodbye"); 

    hi << "hello, world" << std::endl; 
    hi << "Oops, forgot to flush.\n"; 
    bye << "goodbye, cruel world\n" << std::flush; 
    bye << "Cough, cough.\n"; 
} 
+0

Вам даже не нужно, чтобы создать временный регистратор: 'CLogger («привет») <<«привет, мир»<< станд :: епсИ;' – congusbongus

+0

@CongX u - Да, вам нужен именованный объект. Temporaries не могут связываться с неконстантными ссылками, такими как 'operator >> (ostream &, const char *)'. См. Http://stackoverflow.com/questions/14381311/ostrstream-interprets-constant-string-as-pointer –

+0

Любой способ сделать это без использования потоков? – jaho

Смежные вопросы