首页 > 解决方案 > C/C++ 可以在 marco 中使用“for loop”而不是“do while”吗?

问题描述

假设“cond”与程序中的任何名称不冲突,以下两个结构是否等效

#define DOWHILE do { (some_code); } while (0)

#define FORLOOP for(bool cond = true; cond; cond = false) (some_code)

这个问题的目的是:

我有这样的东西

bool printLogs; // nonconstant dynamic variable

而且我有一个宏(我不能做大的改变,这是一个大项目;我必须处理这个宏)#define LOG ... ,它的使用就像

LOG << "message" << 1 << 0.5 << 'a';

我希望这个宏变成

if (printLogs) {
    PrinterClass() << "message" << 1 << 0.5 << 'a';
}

因此,如果未打印,则不会计算打印的参数。在这种情况下,我的解决方案是

#define LOG for(cond = printLogs; cond; cond = false) PrinterClass()

这个解决方案正确吗?还有其他方法吗?

更新:显然你不能if在这里使用简单的。例如此代码将不起作用

#define LOG if(printLogs) PrinterClass()

int main() {
    if (1)
        LOG << 1;
    else
        LOG << 2;
}

更新 2:我希望看到我或您的解决方案正确性的解释。我必须确保该解决方案不会造成任何问题。您可以在代码中可以插入语句的任何位置插入“do while”构造。所以“do while”表现为一个简单的语句。我的建筑是这样吗?

更新 3:具有全局对象的解决方案不满足,因为它会导致巨大的开销

#include <atomic>
void printImpl(...);

std::atomic<bool> printLog;

struct Log {
    template <typename T>
    Log& operator<<(const T& t) {
        if (printLog) { 
            printImpl(t);
        }
        return *this;
    }
};

int main() {
   Log() << 1 << 2;
}

毕竟优化会变成

int main() {
    if (printLog) {
        printImpl(1);
    }
// Still should check because printImpl could have changed this variable.
// C++ does not provide any way to say "I promise it won't change printLog"
    if (printLog) { 
        printImpl(2);
    }
}

所以你对<<的每次使用都有原子比较。见https://godbolt.org/z/sEoUCw

标签: c++macros

解决方案


你可以这样做:

#define LOG if (!printLogs){} else PrinterClass()

推荐阅读