我想做一个类似宏的对象,可以检测到它在当前范围内的使用,在这样的情况下表现不同。例如,考虑以下代码片段
#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
您可以创建一个限定作用域的计时器类:
#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_first
和foo_addition
使用单个foo
,以“方便”宏用户。我的建议是,抵制这种“方便”的冲动,因为它真正做的是隐藏这样一个事实,即它正在做一些不同的事情,这取决于它是哪一个扩展。不要对宏用户隐瞒这个事实--在我看来,让宏用户“不假思索”地使用宏不是一件好事。相反,程序员应该考虑他们编写的代码的效果,并且当使用两个单独的宏名称时,生成的代码更易读,这表明程序员在执行两个单独的操作。
使用宏来减少重复是有道理的;使用宏来模糊程序员的意图是我不会做的。
在对其他潜在解决方案之一的答复中,您指出,您希望宏具有类似于上下文敏感函数的效果,该函数名为initialize_or_print()
。这一事实表明你正在走错误的道路。编程构造应该有单一、明确的目的。当您开始感到需要在一个构造中塞入太多单独的目的时(initialize_or_print_or_spawnnewplayer_or_boilwater()
是您的方向),这可能是一件坏事,应该考虑到单独的部分。