有没有办法为函数创建预处理器宏?

时间:2012-03-23 16:53:02

标签: c++ winapi macros c-preprocessor

是否可以根据函数结果创建C ++预处理器宏?

例如,我想在预处理器宏定义中动态保存屏幕高度:

#define SCREEN_HEIGHT   GetSystemMetrics(SM_CYVIRTUALSCREEN)

然后我想使用结果根据屏幕高度设置值:

#if SCREEN_HEIGHT < 1200
    #define TOP_COORD     200
    #define BOTTOM_COORD  500
    #define LEFT_COORD    0
    #define RIGHT_COORD   1280
#else
    #define TOP_COORD     1100
    #define BOTTOM_COORD  1400
    #define LEFT_COORD    0
    #define RIGHT_COORD   1280
#endif

这不起作用,因为SCREEN_HEIGHT似乎没有得到正确定义。

有没有更好的方法来实现这一目标?这甚至可能吗?我想尽可能在​​头文件中获取此屏幕高度信息,因为这是大量遗留代码的一部分。

4 个答案:

答案 0 :(得分:5)

没有。在编译时,宏在编译时完全评估,至少是由预处理器,在实际代码编译之前,#if等中的表达式必须是预处理器表达式。在程序运行之前,无法知道屏幕的高度。

答案 1 :(得分:2)

不,它无法完成。你期望如何制作编译时的设计,这取决于运行应用程序的屏幕的属性?在编译时你无法知道。

答案 2 :(得分:2)

实际函数通常只被称为运行时。甚至类似函数的事情,例如sizeof(和generalized constant expressions - 感谢@Pubby注释)在预处理阶段之后由编译器评估。到目前为止,所有预处理器内容都已在代码中被替换 - 编译器不知道#if之类的内容。因此,使用宏无法实现所需。

但是,对于模板,它是可能的。第二个想法,不是在这种情况下,因为直到运行时才能知道实际的屏幕高度。

您可以定义一个结构以包含坐标值作为常量,并将所有这些存储在地图或其他形式的集合中,然后在您知道实际屏幕高度时在运行时动态查找。

答案 3 :(得分:0)

如果GetSystemMetrics是一个宏,那么你可以这样做。 如果GetSystemMetricsconstexpr,那么您可以使用特征。

但由于GetSystemMetrics是一个普通的函数,你必须使用普通的C ++。

struct system_metrics_ {
  int top, bottom, left, right;

  system_metrics_()
  {
    if (GetSystemMetrics(SM_CYVIRTUALSCREEN) < 1200) { /* first case */ }
    else { /* second case */ }
  }
};

// define this method outside the header
const system_metrics_& system_metrics() { static system_metrics_ sm; return sm; }

// legacy code
#define TOP_COORD     (system_metrics().top)
#define BOTTOM_COORD  (system_metrics().bottom)
#define LEFT_COORD    (system_metrics().left)
#define RIGHT_COORD   (system_metrics().right)