Представьте, что у вас есть следующий код, где logDebug() стоит дорого или не подходит для вызова более одного раза:
QDebug d = logDebug();
d << __FUNCTION__ << ":";
d << "positions separated with \" --- \":";
for (const auto& str : positions)
{
d << "---" << str;
}
Макрос (просто для правильной замены имени функции) уже существует, который заменяет первые 2 строки:
#define LOG_FUNCTION this->logDebug() << __FUNCTION__ << ":"
Он создает локальную переменную, вызывая logDebug(). После вызова вы можете использовать operator<< только в макросе.
Проблема в том, что вы не можете прикрепить тело цикла for к регистратору.
В: Можно ли использовать макрос для вставки всех позиций (без повторного вызова logDebug?
Я бы предположил, что это должно быть возможно с помощью лямбда-выражений, но я совершенно не знаю, как это сделать.
Помогите пожалуйста, побеждает самый короткий ответ!





Q: Is there a way I could use the macro for pasting all the positions (without calling logDebug again? I would guess this should be possible using lambdas, but I quite don't know how to.
Я полагаю, что это возможно с чем-то следующим (используется std::cout вместо logDebug())
#include <iostream>
#define LOG_FUNCTION std::cout << __FUNCTION__ << ": "
#define LOG_DEB(ps) \
[](auto & s, auto const & _ps) { for ( auto const & p : _ps ) s << p; } \
(LOG_FUNCTION, ps)
int main ()
{
int a[] { 0, 1, 2, 3, 4 };
LOG_DEB(a);
}
Я использовал пару auto в качестве типов лямбда-аргументов, и это работает только начиная с C++14.
В С++ 11 вы должны заменить их правильными типами.
@DrumM - Ну... нет. Это не разные типы лямбда. Это лямбда-определение (до фигурных скобок), вызываемое немедленно (с аргументами std::cout << __FUNCTION__ << ": (etc not repeated part) " и ps). И нет, auto нельзя заменить шаблоном (на данный момент... возможно, начиная с C++20), но вы можете видеть его как шаблон (это синтаксический сахар для шаблона operator() в безымянной структуре); если вам нужно знать тип s, вы можете использовать decltype(s). К сожалению, auto (как тип лямбда-аргумента) доступен только начиная с C++14.
Теперь я понимаю. Хорошим обновлением здесь было бы использование другого имени для второго символа ps, поскольку они разные. При первом чтении это сбивало с толку ;-) В любом случае, это очень хороший фрагмент кода!
@DrumM - Вы правы: хорошее обновление; не потому, что сбивает с толку, а потому, что это имя параметра макроса. Это была очень опасная ошибка.
Ну, макрос можно заставить вернуть ваш объект отладки:
#define LOG_FUNCTION() this->logDebug() << __FUNCTION__ << ":"
Затем используйте его следующим образом:
auto& d = LOG_FUNCTION();
d << "positions separated with \" --- \":";
for (const auto& str : positions)
{
d << "---" << str;
}
Прохладный! Я никогда не видел такого типа лямбда со скобками после фигурных скобок. Этот
autoздесь классный, и я думаю, его можно заменить шаблоном.