c++ - gcc 找不到模板专门化

标签 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 那样的特化?

编辑2:

成功生成 SSCCE http://netload.in/dateiz3R4eTVqi3/src.tar.gz.htm 这里的错误是相反的,但是很好。

编辑3: 固定文件大小:http://netload.in/dateixP6iOvc6bD/src.zip.htm

最佳答案

最小化为:

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(强调我的):

If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required. An implicit instantiation is never generated for an explicit specialization that is declared but not defined.

此外,必须引用下一段(强调我的):

The placement of explicit specialization declarations for function templates, class templates, member functions of class templates, static data members of class templates, member classes of class templates, member enumerations of class templates, member class templates of class templates, member function templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, member class templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.

关于c++ - gcc 找不到模板专门化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24678735/

相关文章:

c++ - 如何有条件地为模板头设置编译器优化

c++ - 将基于堆的 N 元数组引用传递给函数

c - gcc如何判断默认生成32位还是64位的可执行文件?

c++ - fatal error : iostream: No such file or directory in compiling C program using GCC

c++ - GCC 4.7 中是否存在错误。 2's implementation of shared_ptr' s(模板化)赋值运算符?

c++ - try-catch block 可以在 LLVM/MSVC 上编译吗?

c++ - 单独 header 中的 #ifdef 未按预期工作

c++ - boost 返回 0 的 CPU 时间

c++ - #include &lt;header.h>错误: Cannot open source file “header.h”

c++ - 无法将重载函数指针转换为成员函数指针?