【发布时间】:2018-06-06 22:50:12
【问题描述】:
我捕获了由于我正在尝试在标题中提供的定义而捕获重复的符号错误。这是来自Minimal, Complete, and Verifiable example 的错误。头文件和源文件如下所示。
$ clang++ main.cpp x.cpp y.cpp -o main.exe 2>&1 | c++filt
duplicate symbol Id<S>::id in:
/tmp/main-3f2415.o
/tmp/long long-d62c28.o
duplicate symbol Id<T>::id in:
/tmp/main-3f2415.o
/tmp/long long-d62c28.o
duplicate symbol Id<S>::id in:
/tmp/main-3f2415.o
/tmp/unsigned long long-bfa6de.o
duplicate symbol Id<T>::id in:
/tmp/main-3f2415.o
/tmp/unsigned long long-bfa6de.o
ld: 4 duplicate symbols for architecture x86_64
这里是一个类似的问题,但它不涉及专业化:Static member initialization in a class template。这个问题具有专业化,但它适用于MSVC而不是Clang:How to initialize a static member of a parametrized-template class。这个问题声明将它放在源 (*.cpp) 文件中,但我们的目标是让头文件避免 Clang 3.8 和 'Id<S>::id' required here, but no definition is available 警告:Where should the definition of an explicit specialization of a class template be placed in C++?
GCC、ICC、MSVC、SunCC 和 XLC 都可以初始化。 Clang 和 LLVM 给我带来了麻烦。 Clang 和 LLVM 在专业化和 extern 的显式实例化方面也存在问题,所以它有自己的特殊地狱。
我们支持C ++ 03虽然C ++ 17,所以我们必须小心解决方案。我天真地尝试将特化的初始化放在一个未命名的命名空间中,以防止符号转义翻译单元,但这会导致编译错误。
在头文件中初始化和特化模板类时,我们如何避免重复的符号定义?
下面是 MCVE,它是 cat main.cpp a.h s.h s.cpp t.h t.cpp x.cpp y.cpp。问题似乎在a.h,它提供专业化和初始化;和源文件x.cpp和y.cpp,其中包括a.h。
main.cpp
#include "a.h"
#include "s.h"
#include "t.h"
int main(int argc, char* argv[])
{
uint8_t s = Id<S>::id;
uint8_t t = Id<T>::id;
return 0;
}
a.h
#ifndef A_INCLUDED
#define A_INCLUDED
#include <stdint.h>
template <class T> class Id
{
public:
static const uint8_t id;
};
class S;
class T;
template<> const uint8_t Id<S>::id = 0x01;
template<> const uint8_t Id<T>::id = 0x02;
#endif
s.h Em>
#ifndef S_INCLUDED
#define S_INCLUDED
class S {
public:
S();
};
#endif
s.cpp Em>
#include "s.h"
S::S() {}
t.h Em>
#ifndef T_INCLUDED
#define T_INCLUDED
class T {
public:
T();
};
#endif
t.cpp em>
#include "t.h"
T::T() {}
x.cpp
#include "a.h"
y.cpp
#include "a.h"
【问题讨论】:
-
inline没有帮助吗? -
@user0042 - 不,内联编译失败。它在课程和专业上都失败了。
标签: c++ templates initialization static-members template-specialization