我有这三个文件
// foo.h
#pragma once
template <typename T> const T foo;
template <>
const int foo<int> = 1;
// a.cpp
#include "foo.h"
int main() {}
// b.cpp
#include "foo.h"
如果我在Linux上使用GCC 7.5.0构建它们,则可以正常工作:$ g++ -std=c++17 a.cpp b.cpp -o out
$
但是,在Mac上使用Apple Clang 12.0.0时,会出现以下错误:$ clang++ -std=c++17 a.cpp b.cpp -o out
duplicate symbol 'foo<int>' in:
/var/folders/g5/8twmk1xj481_6btvppyw5j4h0000gp/T/a-62bdde.o
/var/folders/g5/8twmk1xj481_6btvppyw5j4h0000gp/T/b-ea4997.o
ld: 1 duplicate symbol for architecture x86_64
这应该是错误,还是Clang中的错误? 最佳答案
它违反了ODR,应为inline
(自C++ 17起)或未命名的namespace
(自C++ 11起)。
为什么违反ODR:
因为foo.h
和a.cpp
都包含b.cpp
,所以在每个翻译单元foo<int>
和a.cpp
中都定义了b.cpp
变量。因此它在该程序中有2个定义,这违反了以前的规则,除非它是未使用的(意味着,不是ODR使用的)或它是inline
变量。
您有2个解决方案:
template<> int const foo<int> = 1;
放入另一个foo.cpp
中。然后只有一个定义。 inline
添加foo
(从C++ 17开始)。一个inline
变量允许翻译单元之间具有多个相同的定义。如果不是在C++ 17中,则可以将其放入未命名的namespace
中,这意味着让其中的所有内容均为inline
。 关于c++ - 使用Clang使用全局模板变量复制符号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64610024/