【问题标题】:template and macro in C++C++中的模板和宏
【发布时间】:2013-10-17 08:27:49
【问题描述】:

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

考虑以下代码:

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&lt;1,1&gt; 什么都不做。

谁能解释为什么会这样? (MSVC 2012)。

【问题讨论】:

  • 不知道为什么这个问题被否决了。看到有多少不好的答案,显然让很多人感到困惑,包括那些认为他们知道这是如何工作的人。

标签: c++ templates macros


【解决方案1】:

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

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);
}

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    【讨论】:

      【解决方案3】:

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

      在您的示例中,您正在比较标记 Signal11。现在,如果 Signal1 本身是一个 makro 并根据某些条件设置其他位置以替换为 12 等,这将是有意义的,但事实并非如此。

      【讨论】:

      • 模板在编译时被大量评估(实例化)。
      • 你这里有个问题,因为你根本不懂模板,但那是你研究的;)
      • 啊,你说得对,我太执着于它是不同的时代,所以我搞砸了......会修复
      • 好的,另外一点就是不理解模板也是完全错误的-_-
      • 好吧,现在是在讨论字符串比较,这又是错误的。 #if 1+1 == 2 是真的。
      【解决方案4】:

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

      此时,没有变量有值,没有函数正在运行,也没有模板参数有值。这类似于 PHP 代码是如何预处理的:底层 HTML 和 PHP 逻辑是完全分开的,不能交互。

      这可能会让人感到困惑,因为您的宏代码看起来在函数模板“内部”,但实际上并非如此:这两个东西存在于不同的存在平面上!

      当没有宏 Signal1Signal2 存在时(这里大概就是这种情况),从预处理器获取输出然后用于处理的代码是这样的:

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

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

        • template &lt;int 1, int Signal2&gt; ... 不,你的宏会破坏模板定义。
        • 天哪,我在想什么。
        猜你喜欢
        • 1970-01-01
        • 2012-05-18
        • 1970-01-01
        • 2015-05-07
        • 2011-04-26
        • 2012-09-29
        • 2010-12-04
        • 2018-11-16
        • 2015-10-16
        相关资源
        最近更新 更多