gcc找不到模板专业化

时间:2014-07-10 14:07:33

标签: c++ templates gcc template-specialization

我的网络代码使用模板特化来序列化不能简单复制的类型。我定义了一个通用模板

template<typename T> struct TypeHandler

处理所有可以通过简单memcpy传输的类型,然后我为所有其他类型定义特化。现在的问题是我有一个具有多个此类特化的文件,如果我使用Visual Studio编译代码,一切正常。但是使用gcc,除了

之外,该文件中的所有模板特化都会被使用
template<> struct TypeHandler<uint32_t>

哪个变量长度对整数进行编码以节省空间。

所有TypeHandler版本的命名空间都是相同的,它们甚至位于同一个文件中。但由于某种原因,gcc决定使用通用版本,我不知道为什么。

编辑:

似乎gcc使用了来自其他项目的TypeHandler的实例化,这个项目链接但不具有uint32_t的特化,即使它传输uint32_t字段。 GCC不会给我任何错误。我如何告诉gcc使用像Visual Studio这样的专业化?

EDIT2:

设法生成SSCCE http://netload.in/dateiz3R4eTVqi3/src.tar.gz.htm 这里的错误是另一种方式,但很好。

EDIT3: 修复了文件大小:http://netload.in/dateixP6iOvc6bD/src.zip.htm

1 个答案:

答案 0 :(得分:3)

最小化为:

test1.cpp

#include <iostream>
#include <stdint.h>

template<typename T>
struct TypeHandler
{
    void Print() { std::cout << "base" << std::endl; }
};


void test1()
{
    std::cout << "p1" << std::endl;
    TypeHandler<uint32_t>().Print();
}

test2.cpp

#include <iostream>
#include <stdint.h>

template<typename T>
struct TypeHandler
{
    void Print() { std::cout << "base" << std::endl; }
};

template<>
struct TypeHandler<uint32_t>
{
    void Print() { std::cout << "int" << std::endl; }
};

void test2()
{
    std::cout << "p2" << std::endl;
    TypeHandler<uint32_t>().Print();
}

main.cpp

void test1();
void test2();
int main(){
    test1();
    test2();
}

在Windows / MinGW 4.8.2上,使用g++ test1.cpp test2.cpp main.cpp -o test进行编译并运行生成

p1
base
p2
base

使用g++ test2.cpp test1.cpp main.cpp -o test生成

p1
int
p2
int

这是一种直接的标准违规,导致未定义的行为。您无法在一个翻译单元中明确专门化相同的模板,而不能在另一个翻译单显式特化在test1.cpp中不可见,导致编译器从基本模板生成隐式实例化。所以你得到两个TypeHandler<uint32_t>特化,在这个例子中,链接器似乎决定从它看到的第一个目标文件中选择一个。来自标准的§14.7.3[temp.expl.spec] / p6(强调我的):

  

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

另外,下一段的强制性引用(强调我的):

  

为函数放置显式特化声明   模板,类模板,类模板的成员函数,   类模板的静态数据成员,类的成员类   模板,类模板的成员枚举,成员类   类模板的模板,类的成员函数模板   模板,类模板成员模板的成员函数,   非模板类的成员模板的成员函数,成员   类模板的成员类的函数模板等   放置类模板的部分特化声明,   非模板类的成员类模板,成员类模板   类模板等可以影响程序是否格式正确   根据显式专业化的相对定位   声明及其在翻译单元中的实例化要点   如上下文所述。 撰写专业时,请   小心它的位置;或者使它编译将是这样的试验   点燃自焚。