我有一个带有特化的显式实例化模板类:
// 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中被隐式实例化,即使在该翻译单元中没有使用此规范。
答案 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显式专用类的成员不是隐式的 从类模板的成员声明中实例化; 相反,类模板特化的成员应该自己 如果需要定义,则明确定义。