C ++中的模板和宏

时间:2013-10-17 08:27:50

标签: c++ templates macros

不是计算机科学背景,当涉及到宏时,我对模板有点困惑:

考虑以下代码:

template <int Signal1, int Signal2>
void my_add(int & x, int y)
{
#if Signal1==1||Signal2==1
    x+=y;
#endif 
}

//And call the template, e.g.: my_add<1, 1>(x, 3);

问题是,似乎#if宏无法按预期工作,就像#if宏测试始终返回false一样,结果为my_add<1,1>什么都不做。

任何人都可以解释为什么会这样? (MSVC 2012)。

5 个答案:

答案 0 :(得分:4)

这就是你真正想要的东西,而且这不是微不足道的:

template <bool defaultCase> class Adder
{
   static void my_add(int & x, int y) { }
};

template < > class Adder<true>
{
   static void my_add(int & x, int y) { x += y; }
};

template <int Signal1, int Signal2>
void my_add(int & x, int y)
{
   Adder<Signal1==1 || Signal2==1>::my_add(x,y);
}

这是一个部分特化,它需要一个类模板。函数模板没有部分特化,因为它会干扰重载,但这里模板参数不参与重载。

答案 1 :(得分:1)

您将模板使用的Signal1 / Signal2类型与预处理器使用的符号常量混淆 - 两个不同的“域”。

在预处理阶段(实际编译之前)评估宏符号并使用符号。

模板类型是在编译阶段定义的(如果模板是实例化的。)

虽然两者都使用相同的“名称”,但预处理器仍然没有定义任何Signal1 / 2符号。

以下链接可能有所帮助: Preprocessor directives

答案 2 :(得分:1)

简而言之:模板在编译时进行评估,但以#开头的任何内容都是 pre - 处理器语句,并在之前进行评估/ em>代码已编译。我希望你看到这两个不能按照你的意图混合。

在您的示例中,您要比较代币Signal11。现在,如果Signal1本身就是一个makro并将其他地方设置为替换为12等,这取决于某些条件,这是有道理的,但事实并非如此。

答案 3 :(得分:0)

宏不关心甚至不了解模板。宏只是通过搜索和替换源代码文件中的字符和行来完成,就在它即将被编译之前。

此时,没有变量具有值,没有正在运行的函数,并且没有模板参数具有值。它类似于PHP代码预处理:底层HTML和PHP逻辑彼此完全分离,无法进行交互。

这可能令人困惑,因为您的宏代码看起来像它在函数模板的“内部”,但实际上并非如此:这两件事存在于不同的存在层面上!

当没有宏Signal1Signal2时(这可能是这里的情况),从预处理器输出然后用于处理的代码是:

template <int Signal1, int Signal2>
void my_add(int & x, int y)
{
}

答案 4 :(得分:-2)

<击> 宏无法获取类型信息。它在编译器之前调用。宏中的Signal1和Signal2与模板参数无关。

使用#define Signal1 1x+=y将在您的模板中生效。 请记住 - 这是在根据您的使用情况扩展模板之前发生的。

编辑:问题是关于部分专业化。让这个作为一个温和的“不要突袭问题”提醒。