gcc使用专门的定义内联通用模板函数

时间:2017-05-03 02:22:38

标签: c++ templates gcc inline compiler-optimization

我怀疑gcc 4.8.3是否内联不正确的模板函数......在调试模式下不会出现此问题,但仅在优化模式下。然而,这发生在复杂的代码库中,我无法在简单的测试用例中重现该问题。

我的代码如下

#include "stdio.h"

class A {
 public:

    template<typename T> int WriteNative(const T) { 
      printf("here?\n")
      return 0; 
    }

    template<typename D> 
        void doit() {
        if (WriteNative<double>(1)) {
            printf("A\n");
        } else {
            printf("B\n");
        }
    }

};

// in my real code, this definition is in a different cpp file
template<> int A::WriteNative<double>(const double) { 
  return 1; 
}

int main() {
    A a;
    a.doit<float>();
}

在调试版本中,它打印出A,而在优化版本中,它会打印出来吗?\ nB

我猜任何内联都使用通用模板函数定义,但不使用专用函数定义。但属性((noinline))无济于事。

如果我的代码具有C ++的已定义行为,是否有人?以及如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

您没有明确说明这一点,但我在您的实际代码中猜测您未能在A的.h文件中声明专业化。因此,当A.h包含在单独的编译单元中时,编译器不知道WriteNative()的特殊值。添加专业化声明应该解决问题,而不必将定义包含在同一个文件中(即,不必内联它):

class A {
    public:
    template<typename T> int WriteNative(const T) { 
      printf("here?\n")
      return 0; 
    }

    template<typename D> 
        void doit() {
        if (WriteNative<double>(1)) {
            printf("A\n");
        } else {
            printf("B\n");
        }
    }
};
template<> int A::WriteNative(const double);

您可以使用三个文件A.hA.cppmain.cpp来重现您的问题,其中A.cpp包含专精的定义,以便在{{1包含main.cpp,在优化期间发生内联时不知道特化,当使用A.h进行编译时,不会发生内联,因此-O0与{{1}中的定义相关联}}

编辑: 请参阅此answer,其中引用了规范来解释为什么这是正确的行为。

14.7.3 [temp.expl.spec]:

  

6 /如果是模板,成员模板或类模板的成员   明确专业化然后宣布专业化   在第一次使用该特化之前会导致一个   隐式实例化发生在每个翻译单元中   发生了这种用途;无需诊断。如果是程序   没有为显式专业化提供定义   专业化的使用方式会导致   隐式实例化发生或成员是虚拟成员   功能,程序格式错误,无需诊断。一个   永远不会为显式生成隐式实例化   声明但未定义的特化。