避免由于头中的专业化初始化而导致重复符号? [英] Avoiding duplicate symbol due to initialization of specialization in header?

查看:126
本文介绍了避免由于头中的专业化初始化而导致重复符号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于要在标头中提供的定义,我正在捕获重复的符号错误.这是最小,完整和可验证的示例中的错误.头文件和源文件如下所示.

I'm catching duplicate symbol errors due to definitions I am trying to provide in a header. Here's the error from the Minimal, Complete, and Verifiable example. The header files and source files are shown below.

$ 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

这是一个类似的问题,但不涉及专门化:类模板中的静态成员初始化.这个问题有专门知识,但它是针对MSVC而不是Clang的:如何初始化参数化模板类的静态成员 .这个问题要求将其放入源(* .cpp)文件中,但是我们的目标是避免lang 3.8和 'Id<S>::id' required here, but no definition is available 警告的头文件:

Here is a similar question, but it does not involve a specialization: Static member initialization in a class template. This question has the specialization but it is for MSVC and not Clang: How to initialize a static member of a parametrized-template class. And this question states to put it in the source (*.cpp) file but we are aiming for the header file to avoid Clang 3.8 and 'Id<S>::id' required here, but no definition is available warnings: 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的显式实例化方面也遇到麻烦,因此它拥有特殊的地狱.

GCC, ICC, MSVC, SunCC and XLC are OK with the initialization. Clang and LLVM is giving me the trouble. Clang and LLVM also has trouble with explicit instantiations of specializations and extern, so its it own special kind of hell.

我们通过C ++ 17支持C ++ 03,因此我们必须小心解决方案.天真地尝试将专业化的初始化放在一个未命名的命名空间中,以防止符号转义翻译单元,但这会导致编译错误.

We support C++03 though C++17, so we have to be careful of the solution. Naively I tried placing the initialization of the specializations in an unnamed namespace to keep the symbols from escaping the translation units, but it resulted in compile errors.

在标头中初始化和专用化模板类时,如何避免重复的符号定义?

How do we avoid duplicate symbol definitions when initializing and specializing a template class in a header?

下面是MCVE,它是cat main.cpp a.h s.h s.cpp t.h t.cpp x.cpp y.cpp.问题似乎出在a.h上,它提供了专业化和初始化功能.以及包含a.h的源文件x.cppy.cpp.

Below is the MCVE, which is a cat main.cpp a.h s.h s.cpp t.h t.cpp x.cpp y.cpp. The problem seems to be with a.h, which provides the specialization and initialization; and the source files x.cpp and y.cpp, which include a.h.

main.cpp

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

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

s.h

#ifndef S_INCLUDED
#define S_INCLUDED

class S {
public:
    S();
};

#endif

s.cpp

s.cpp

#include "s.h"

S::S() {}

t.h

t.h

#ifndef T_INCLUDED
#define T_INCLUDED

class T {
public:
    T();
};

#endif

t.cpp

t.cpp

#include "t.h"

T::T() {}

x.cpp

x.cpp

#include "a.h"

y.cpp

y.cpp

#include "a.h"

推荐答案

您可以使用 未命名空间 ,可以使您的类具有内部链接,例如

You can use unnamed namespace which can make your class have internal linkage, e.g.

#ifndef A_INCLUDED
#define A_INCLUDED

#include <stdint.h>

namespace {
    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

在您的示例中用a.h中的内容替换此代码,然后它将起作用,因为由于内部链接,一个翻译单元中的Id<T>与另一翻译单元中的Id<T>不同,因此不违反一个定义规则

Replace this code with the contents in a.h in your example, then it will work because Id<T> in one translation unit is different from that in another translation unit due to internal linkage, thus one-definition rule is not violated.

这篇关于避免由于头中的专业化初始化而导致重复符号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆