2015-06-25 1 views
0

У меня есть этот код для патентованного регистратора:Блокировка выходного ostream в макро

#define LOG GetStream() 

Где GetStream возвращает зЬй :: ostream. Пользователь будет делать:

LOG << "text"; 

мне это нужно, чтобы быть потокобезопасными, но хотел бы избежать этого:

#define END Unlock(); 
#define LOG Lock(); GetStream() << "text" << END; 

Поскольку пользователю нужно будет добавить "END":

LOG << "Text" << END; 

Есть идеи?

Примечание: Я обрабатываю возврат каретки, используя что-то вроде this.

+2

почему это в макрос все равно –

+1

You мог бы обеспечить обертку логгером относительно легко, вместо того, чтобы идти уродливым способом с помощью макросов. – Hiura

ответ

2

Одним из способов решения этой проблемы является использование макросов функции в стиле, где вы включить запирание/отпирание с помощью C++ блок и область видимости:

#define LOG(output)    \ 
    do       \ 
    {        \ 
     LockingClass lock;  \ 
     GetStream() << output; \ 
    } while (0) 

LockingClass (или что вы хотите назвать его) это фиксированный замок, который блокирует поток при строительстве и разблокирует его при разрушении.

Может использоваться как, например,

LOG("hello variable is " << variable); 

Не можете использовать его с выражениями, содержащими запятую, хотя, препроцессор будет интерпретировать запятые в качестве разделителя аргументов для макроса. Вероятно, это можно решить с помощью variadic macros.

+0

снова, это альтернативный способ. вы не можете сделать это с помощью оператора '<<'. –

0

TL; вы не можете сделать целое x<<text<<end работать только макросами.

для того, чтобы положить много выражений точкой с запятой (;) с макро, единственный правильный путь, используя do{..} while(0) заявление, вы можете прочитать об этом подробнее здесь: do { ... } while (0) — what is it good for?

теперь все хорошо, пока вы не хотите для использования некоторых операторов, таких как <<, тогда вы не можете использовать калькуляцию do{..} while(0).

мое предложение: оберните std::ostream в классе, где вы перегрузите оператор <<. внутри перегрузки, звоните Lock и Unlock.

struct MyLogger{ 
    std::ostream& operator << (Text text){ 
    Lock(); 
    stream <<text; 
    Unlock(); 
    return stream; 
    } 
} 

, где stream - это поток, в который вы передаете текст.

сейчас, вы можете создать объект из этого класса и использовать регулярно, не-макро <<:

NyLogger Log; 
Log << text; 
+0

Я отредактировал это, чтобы исправить слишком много ';'.Тем не менее, я думаю, что по-прежнему неправильно говорить, что '<<' не будет работать с 'do {...} while (0)'. Почему ты говоришь это? Ответ Йоахима хорошо работает с 'do {...} while (0)' –

+1

, он использует '<<' внутри do .. while. он не принимает никакого выражения с уже «<<» и заставляет его работать с макросом. он в основном работает с макросом X (Y), а не X << Y. это моя точка зрения. –

+0

Ах да, я вижу. Вопроситель хочет иметь возможность использовать «макрос» как «LOG << stuff;», но мы можем только реализовать «LOG (материал)», внутри макросов. Согласовано. Ваше единственное решение, которое, я думаю, допускает 'LOG << stuff;' (где 'stuff' имеет тип' Text') –

1

Просто хотя это:

#define LOG for (int i = 0 ;i < 1 ;i++,(i == 1 ? Unlock())) LockAndGetStream() 
+1

Хотя код выглядит настолько отвратительным, это делает именно то, о чем просил хрюканье. +1 И тогда я осознал его сам. – user2883715

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