不是计算机科学背景,当涉及到宏时,我对模板有点困惑:
考虑以下代码:
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
)。
答案 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>代码已编译。我希望你看到这两个不能按照你的意图混合。
在您的示例中,您要比较代币Signal1
和1
。现在,如果Signal1
本身就是一个makro并将其他地方设置为替换为1
,2
等,这取决于某些条件,这是有道理的,但事实并非如此。
答案 3 :(得分:0)
宏不关心甚至不了解模板。宏只是通过搜索和替换源代码文件中的字符和行来完成,就在它即将被编译之前。
此时,没有变量具有值,没有正在运行的函数,并且没有模板参数具有值。它类似于PHP代码预处理:底层HTML和PHP逻辑彼此完全分离,无法进行交互。
这可能令人困惑,因为您的宏代码看起来像它在函数模板的“内部”,但实际上并非如此:这两件事存在于不同的存在层面上!
当没有宏Signal1
或Signal2
时(这可能是这里的情况),从预处理器输出然后用于处理的代码是:
template <int Signal1, int Signal2>
void my_add(int & x, int y)
{
}
答案 4 :(得分:-2)
<击> 宏无法获取类型信息。它在编译器之前调用。宏中的Signal1和Signal2与模板参数无关。
使用#define Signal1 1
和x+=y
将在您的模板中生效。
请记住 - 这是在根据您的使用情况扩展模板之前发生的。
击>
编辑:问题是关于部分专业化。让这个作为一个温和的“不要突袭问题”提醒。