Russian Qt Forum
Ноябрь 25, 2024, 04:41 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Хитрые макросы QLogCat  (Прочитано 3528 раз)
ammaximus
Гость
« : Ноябрь 08, 2013, 13:09 »

QLogCat - мой отладчик для работы через сеть. Сочетает в себе элементы QDebug и LogCat.

Код:
// Макроконтур
#define qlc MacroCall()
#define qlcv MacroCall(QLC::Verbose)
#define qlcd MacroCall(QLC::Debug)
#define qlci MacroCall(QLC::Info)
#define qlcw MacroCall(QLC::Warning)
#define qlce MacroCall(QLC::Error)
#define qlca MacroCall(QLC::Assert)
#define qlcf MacroCall(QLC::Fatal)

class QLCSHARED_EXPORT QLC
{
public:
    // Уровень сообщения
    enum LevelType{
        Verbose=0,  // Временное отладочное сообщение (не должно быть фиксировано)
        Debug=1,    // Отладка
        Info=2,     // Информирующее сообщение
        Warning=3,  // Предупреждение
        Error=4,    // Ошибка
        Assert=5,   // Утверждение
        Fatal=6     // Фатальная ошибка
    };

    QLC(QString file, int line, LevelType type, QString log = QLC_DEFTAG);  // Создание объекта
    ~QLC(); // То самое место, которое отправляет по завершению цепочки <<

    QLC& operator<<(const QVariant var);
};

class QLCSHARED_EXPORT MacroCall
{
    QLC::LevelType level;
public:
    MacroCall()
        :level(QLC::Debug){}

    MacroCall(QLC::LevelType l)
        :level(l){}

    QLC operator()(){
        return QLC(__FILE__, __LINE__, level);
    }
    QLC operator()(QString log){
        return QLC(__FILE__, __LINE__, level, log);
    }
};

#endif // QLC_H
qlc - библиотека QLogCat. Отправка сообщений осуществляется через вызов макросов qlc или qlcX, где Х - уровень сообщения. Макросы подставляют вместо себя объект MacroCall, у которого перегружена операция (). Конструктор MacroCall получает параметр Х и запоминает его. Затем, в зависимости от набора аргументов, оператор () создает нужный QLC. Чтобы послать сообщение в QLC используется <<.

Использование
Код:
qlc("Logname") << "Hello";

    //qlce("NotWorkLog") << "Message";
    //MacroCall(QLC::Error)("NotWorkLog") << "Message";

    MacroCall a(QLC::Error);
    a("DasCool") << "That's work!";

Итак проблема. Закомментированный код не работает, но если развернуть его на две части все ок. Что можно сделать с ()() Непонимающий

Ошибка invalid use of qualifid-name
« Последнее редактирование: Ноябрь 08, 2013, 13:12 от ammaximus » Записан
Bepec
Гость
« Ответ #1 : Ноябрь 08, 2013, 15:03 »

В первом исполняется конструктор и он не в курсах что ты там делаешь дальше с операторами. Это ж конструктор.
А если разложить, то конструктор создаёт объект и вызывает у объекта оператор скобочек.
Записан
ammaximus
Гость
« Ответ #2 : Ноябрь 08, 2013, 15:09 »

Мне не понятно, два конструктора, с параметром и без, в одном классе, написаны подряд.
Так работает
Код:
MacroCall()("NotWorkLog") << "Message";
Так нет
Код:
MacroCall(QLC::Error)("NotWorkLog") << "Message";
Записан
ammaximus
Гость
« Ответ #3 : Ноябрь 09, 2013, 12:56 »

Минимальный нерабочий код в студию:
Код:
#include <QVariant>
#include <QDebug>

class QLC
{
public:
// Error types
    enum LevelType{
        Debug=0,  // Debug
        Error=1,  // Error
        WTF = 2   // WTF???
    } level;

    QString logger;

// Constructors
    QLC(QLC::LevelType l)
        :level(l), logger(":")
    {}

    QLC(QLC::LevelType l, QString log)
        :level(l), logger(log)
    {}

// OPERATOR <<
    QLC& operator<<(const QVariant var){
        qDebug() << "(" + QString::number(level) + ")" << logger << var;
    }
};

class MacroCall
{
    QLC::LevelType level;
public:
    MacroCall()
        :level(QLC::Debug){}

    MacroCall(int i)
        :level(QLC::WTF){}

    MacroCall(QLC::LevelType l)
        :level(l){}

    QLC operator()(){
        return QLC(level);
    }
    QLC operator()(QString log){
        return QLC(level, log);
    }
};

int main(int argc, char*argv[])
{
    MacroCall()("WorkLog") << "No level, yes logname";
    MacroCall(QLC::Error)() << "No logname, yes level";

    MacroCall a(QLC::Error);
    a("WorkLog") << "Logname and level at different lines";

    // GET READY!
    // INT as level and logname:
    MacroCall(2)("WorkLog") << "WTF?? It works!";

    //MacroCall(QLC::WTF)("NotWorkLog") << "It's not work!!!!!!";
    // NOT WORK: error: invalid use of qualified-name 'QLC::WTF'
    // Qt 4.8.3

    return 0;
}
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #4 : Ноябрь 09, 2013, 15:40 »

Непонятно зачем вообще MacroCall обязательно должен быть классом?

Можно, например, так:
Код
C++ (Qt)
template <QLC::LevelType level = QLC::Debug>
QLC MacroCall(const QString & log = QString()) {
   return QLC(level, log);
}
 
...
 
MacroCall<QLC::Error>("WorkLog") << " message ";
MacroCall<>("WorkLog") << " message ";
 
« Последнее редактирование: Ноябрь 09, 2013, 15:42 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
ammaximus
Гость
« Ответ #5 : Ноябрь 10, 2013, 14:43 »

Искать решение за пределами проблемы  Веселый Когда-нибудь и я так буду.

Обнаружили интересный момент: http://stackoverflow.com/questions/19874867/enum-in-constructor-qt-c

Проблему уже решил отказом от использования енумов:

Код:
#define qlcv MacroCall(__FILE__, __LINE__, 0)
#define qlcd MacroCall(__FILE__, __LINE__, 1)
#define qlci MacroCall(__FILE__, __LINE__, 2)
#define qlcw MacroCall(__FILE__, __LINE__, 3)
#define qlce MacroCall(__FILE__, __LINE__, 4)
#define qlca MacroCall(__FILE__, __LINE__, 5)

 MacroCall(QString f, int l, int type)
        :level(QLC::LevelType(type)), file(f), line(l){}


Шаблоны круто, будет время - перепишу, для общего развития
« Последнее редактирование: Ноябрь 10, 2013, 19:48 от ammaximus » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.071 секунд. Запросов: 23.