专门模板的多个实例化

时间:2015-07-10 14:18:37

标签: c++ templates template-specialization specialization explicit-instantiation

我有一个带有特化的显式实例化模板类:

// a.hh
#pragma once

template<int N>
struct A {
  int foo();
};

// a.in
#include "a.hh"

template<>
int A<1>::foo() { return 1; } // specialization for N=1

template<>
int A<2>::foo() { return 2; } // specialization for N=2

// a1.cc
#include "a.in"

template struct A<1>; // explicit instantiation for N=1

// a2.cc
#include "a.in"

template struct A<2>; // explicit instantiation for N=2

上述文件使用g ++ 4.9.2编译成静态库:

g++ -Wall -c -o a1.o a1.cc
g++ -Wall -c -o a2.o a2.cc
ar rcs libtest.a a1.o a2.o

我希望a1.o包含A&lt; 1&gt; :: foo(),而a2.o包含A&lt; 2&gt; :: foo(),但不是相反,因为只有一个实例化每个.cc文件。

然而,事实证明,两个目标文件都包含这两个功能。 VS2015RC还提供链接器警告:

a1.obj : warning LNK4006: "public: int __thiscall A<1>::foo(void)" already defined in a2.obj; second definition ignored
a1.obj : warning LNK4006: "public: int __thiscall A<2>::foo(void)" already defined in a2.obj; second definition ignored

为什么?

另外,如果我注释掉N = 2的特化,那么使用g ++它仍然可以静默编译,即使显式实例化的N = 2情况有一个未解析的函数......(VS2015RC警告说&#34;没有合适的定义提供了显式模板实例化请求&#34;,如预期的那样。)

澄清 - 根据标准(14.7.3.6):

  

如果类模板的[..]成员是显式专用的,那么该特化应在第一次使用该特化之前声明,这将导致发生隐式实例化,在每个发生此类使用的翻译单元中[。]

这段(隐含地)指出,需要使用专门化才能实例化。

我的问题是A&lt; 2&gt; :: foo()在a1.o中被隐式实例化,即使在该翻译单元中没有使用此规范。

2 个答案:

答案 0 :(得分:2)

您的专业化不是inline。所以你有一个翻译单位的定义,包括 a.in

添加inline关键字:

template<>
inline int A<1>::foo() { return 1; } // specialization for N=1

或在cpp文件中移动定义:

// a1.cc
#include "a.hh"

template<>
int A<1>::foo() { return 1; } // specialization for N=1

template struct A<1>; // explicit instantiation for N=1

答案 1 :(得分:1)

我会说你的代码

template<>
int A<1>::foo() { return 1; } // specialization for N=1

这是成员函数的一个明确的定义,因此不能两次完成。因此,请确保仅在一个翻译单元内。

  

14.7.3明确的专业化

     

5显式专用类的成员不是隐式的   从类模板的成员声明中实例化;   相反,类模板特化的成员应该自己   如果需要定义,则明确定义。