提问者:小点点

如何检测当前作用域中已使用宏?


我想做一个类似宏的对象,可以检测到它在当前范围内的使用,在这样的情况下表现不同。例如,考虑以下代码片段

#define FOO /* expand to printf("first time\n"); or printf("not a first time\n"); */

{
   FOO // prints "first time"

   FOO // prints "not a first time"

   {
       FOO // prints "first time"

       FOO // prints "not a first time"
   }

   FOO // prints "not a first time"
}

有没有可能在C++中用宏或任何其他语言元素来实现这一点?

对于那些好奇为什么我需要这样做的人:我想要制作一个易于复制、可粘贴的宏FOO,我可以将它放在任何地方,以便在两次出现之间花费时间在代码片段上。

例如:

FOO // initialize timer
// code fragment 1
FOO // print the time spent in code fragment 1
// code fragment 2
FOO // print the time spent in code fragment 2
// code fragment 3
FOO // print the time spent in code fragment 3

共3个答案

匿名用户

您可以创建一个限定作用域的计时器类:

#include <chrono>
#include <iostream>
#include <thread>

class ScopedTimer {
    using clock = std::chrono::steady_clock;
    std::chrono::time_point<clock> _begin;

public:
    ScopedTimer() : _begin{ clock::now() }
    {}

    ScopedTimer(ScopedTimer const&) = delete;
    ScopedTimer& operator=(ScopedTimer const&) = delete;

    void print_duration() {
        using namespace std::chrono;
        auto const duration = duration_cast<milliseconds>(clock::now() - _begin);
        std::cout << "Duration: " << duration.count() << '\n';
    }
};

int main() {
    ScopedTimer timer{};
    std::this_thread::sleep_for(std::chrono::seconds(1));
    timer.print_duration();
    std::this_thread::sleep_for(std::chrono::seconds(1));
    timer.print_duration();
}

匿名用户

这个怎么样?

#define FOO(block) /* The code section to time */ \
do{                                               \
    /* code for start of timing */                \
    { block }                                     \ 
    /* code for end of timing */                  \
while(0);                                         \

匿名用户

C预处理器宏通常不受欢迎。虽然在您的情况下,您正在使用它们来减少printf(“第一次\n”)的重复;并且减少代码中的重复是一件好事。假设我们只想考虑基于宏的解决方案,我会这样做:

#define FOO_FIRST printf("first time\n");
#define FOO_ADDITIONAL printf("not a first time\n");
{
   FOO_FIRST // prints "first time"
   FOO_ADDITIONAL // prints "not a first time"
   {
       FOO_FIRST // prints "first time"
       FOO_ADDITIONAL // prints "not a first time"
   }
   FOO_ADDITIONAL // prints "not a first time"
}

您最初发布的解决方案试图为foo_firstfoo_addition使用单个foo,以“方便”宏用户。我的建议是,抵制这种“方便”的冲动,因为它真正做的是隐藏这样一个事实,即它正在做一些不同的事情,这取决于它是哪一个扩展。不要对宏用户隐瞒这个事实--在我看来,让宏用户“不假思索”地使用宏不是一件好事。相反,程序员应该考虑他们编写的代码的效果,并且当使用两个单独的宏名称时,生成的代码更易读,这表明程序员在执行两个单独的操作。

使用宏来减少重复是有道理的;使用宏来模糊程序员的意图是我不会做的。

在对其他潜在解决方案之一的答复中,您指出,您希望宏具有类似于上下文敏感函数的效果,该函数名为initialize_or_print()。这一事实表明你正在走错误的道路。编程构造应该有单一、明确的目的。当您开始感到需要在一个构造中塞入太多单独的目的时(initialize_or_print_or_spawnnewplayer_or_boilwater()是您的方向),这可能是一件坏事,应该考虑到单独的部分。