当前位置: 首页 > 知识库问答 >
问题:

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

祖麻雀
2023-03-14

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

#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个答案

汤飞羽
2023-03-14

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

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

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

虞唯
2023-03-14

这个怎么样?

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

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

#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();
}
 类似资料:
  • 问题内容: 在iPhone和iPad之间检测到的Swift 相当于什么? 在Swift中编译时出现错误。 问题答案: 使用Swift时,您可以使用 ,定义为: 因此,您可以将其用作: 或使用Switch语句: 是一个Objective-C宏,定义为: 另外,请注意,即使在使用Objective-C时,也仅在定位iOS 3.2及更低版本时才需要该宏。部署到iOS 3.2及更高版本时,可以直接使用。

  • 我试图使用Groovy管道脚本获取Jenkins构建的当前工作区: 它返回:

  • 问题内容: 我有一个externalItems列表。在每个externalItem内,我都有一个innerItems列表。它们是动态排序的。 当鼠标光标指向innerItems之一时,我必须在该innerItem元素上方显示弹出窗口。 Popup div是body的孩子,因为我不想为innerItems的每个单独创建一个弹出窗口。 我所看到的方式—在我调用的函数中,将左/上属性设置为绝对定位的弹出

  • 我想知道是否可以通过spotify web api从用户当前的活动设备中检测出用户正在听的歌曲。 谢谢。

  • 我想问,如何在Java中检测关键区域?我知道这是用两个原子过程实现互斥,但我只是想知道什么是确定这是一个关键区域的一般情况。 我很想知道: > 在Java中,关键区域是否只存在于并发系统中?

  • nuxt3如何在服务端获取当前域名,服务端无法使用location去获取 使用useRequestHeaders获取的空对象