Там должен так или иначе записать следующее как макрос C++?

my_macro << 1 << "hello world" << blah->getValue() << std::endl;

должен расшириться в:

std::ostringstream oss;
oss << 1 << "hello world" << blah->getValue() << std::endl;
ThreadSafeLogging(oss.str());
20
задан m0nhawk 6 July 2017 в 06:41
поделиться

6 ответов

No. Проблема в том, что без использования синтаксиса функции макрос ограничивается заменой только там, где он есть.

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

my_macro(1 << "hello world" << blah->getValue() << std::endl);

Вы можете определить MyMacro как:

#define my_macro(args) std::ostreamstring oss; \
                       oss << args; \
                       ThreadSafeLogging(oss.str());
-121--2170220-

Похоже, что viewForHeaseInSection вызывается раньше, чем «» ForHeaseInSection «». Однако если для определенной строки, в которой не требуется использовать представление, возвращается значение nil, вызывается startForHeireInSection.

-121--3390932-
#define my_macro my_stream()
class my_stream: public std::ostringstream  {
public:
    my_stream() {}
    ~my_stream() {
        ThreadSafeLogging(this->str());
    }
};
int main() {
    my_macro << 1 << "hello world" << std::endl;
}

Создается временный поток типа my _ , который является подклассом ostringstream . Все операции с этой временной системой работают так же, как и в ostringstream .

Когда оператор заканчивается (т.е. сразу после точки с запятой на всей операции печати в main ()) временный объект выходит из области действия и уничтожается. Деструктор my _ stream вызывает ThreadSafeLogging с ранее собранными данными.

Протестировано (г++).

Спасибо/кредит динго за указание на то, как упростить все это, поэтому мне не нужен перегруженный оператор < < . Слишком плохие upvotes не могут быть общими.

73
ответ дан 29 November 2019 в 22:31
поделиться

Не могли бы вы просто унаследовать от ostream и предоставить свою собственную потокобезопасную реализацию? Тогда вы могли бы просто сделать

myCOutObject << 1 << "hello world" << blah->getValue() << std::endl;

И получить ту же функциональность без макросов и при правильном использовании C ++?

3
ответ дан 29 November 2019 в 22:31
поделиться

Взгляните на google-glog , они делают это с помощью временного объекта, созданного с помощью

LOG(INFO) << "log whatever" << 1;

, и у них также есть другие интересные макросы, такие как LOG_IF et al.

2
ответ дан 29 November 2019 в 22:31
поделиться

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

Но если вы хотели использовать синтаксис функции, вы можете заменить вещи как до, так и после аргументов.

my_macro(1 << "hello world" << blah->getValue() << std::endl);

Вы можете определить MyMacro как:

#define my_macro(args) std::ostreamstring oss; \
                       oss << args; \
                       ThreadSafeLogging(oss.str());
2
ответ дан 29 November 2019 в 22:31
поделиться

Вот еще один неприятный трюк, который я видел где-то еще. У него есть существенный недостаток по сравнению с моим другим ответом: вы не можете использовать его дважды в одной и той же области, потому что он объявляет переменную. Тем не менее, это может быть интересно для других случаев, когда вы хотите, чтобы somemacro foo запускал что-то после foo .

#define my_macro \
    std::ostringstream oss; \
    for (int x=0; x<2; ++x) \
        if (x==1) ThreadSafeLogging(oss.str()); \
        else oss

int main() {
    my_macro << 1 << "hello world" << std::endl;
}
1
ответ дан 29 November 2019 в 22:31
поделиться

Учитывая, что эти строки включены где-то в коде, да, возможно, макрос

#include <iostream>
#include <sstream> 

__ LINE __ определяется всеми стандартными компиляторами. {{ 1}} Таким образом, мы можем использовать его для генерации имени переменной, которое меняется каждый раз, когда вы используете макрос:)

Вот новая версия, которая рассматривается только как инструкция с одним оператором: (EDITED )

#define Var_(Name, Index) Name##Index
#define Var(Name, Index) Var_(Name, Index)
#define my_macro \
for (struct { int x; std::ostringstream oss; } Var(s, __LINE__) = { 0 }; \
     Var(s, __LINE__).x<2; ++Var(s, __LINE__).x)  \
    if (Var(s, __LINE__).x==1) ThreadSafeLogging(Var(s, __LINE__).oss.str()); \
    else Var(s, __LINE__).oss

// So you can use it like this 
int main() 
{ 
    if (4 != 2)
        my_macro << 4 << " hello "  << std::endl; 
    my_macro << 2 << " world !" << std::endl; 
} 

Разработчику, вероятно, не потребуется использовать этот макрос дважды в одной строке из-за простоты оператора << . Но если вам это нужно, вы можете переключить использование __ LINE __ на __ COUNTER __ (что нестандартно!). Спасибо Quuxplusone за этот совет

2
ответ дан 29 November 2019 в 22:31
поделиться
Другие вопросы по тегам:

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