我在一个项目的CI构建中遇到了一个奇怪的错误。这只发生在相对较老的操作系统(Ubuntu 16.04)和不太新的编译器(gcc 5.4.0)上。
导致错误的代码类似于以下内容:(https://godbolt.org/z/MhY6sv)
导致错误的代码类似于以下内容:(https://godbolt.org/z/MhY6sv)
#include <limits>
#include <string>
#define DEFAULT_INIT(x) x{defaultValue<decltype(x)>}
namespace MyProject{
template<typename T>
class Arr1 : public std::array<T, 3>{
public:
Arr1(T t1, T t2, T t3) : std::array<T, 3>{{t1, t2, t3}}{}
};
template<typename T>
class Arr2 : public std::array<T, 3>{
Arr2(T t1, T t2, T t3) : std::array<T, 3>{{t1, t2, t3}}{}
};
namespace{
template <typename T> constexpr T defaultValue = std::numeric_limits<T>::max();
template <typename T> const Arr1<T> defaultValue<Arr1<T>> = Arr1<T>{defaultValue<T>, defaultValue<T>, defaultValue<T>};
template <typename T> const Arr2<T> defaultValue<Arr2<T>> = Arr2<T>{defaultValue<T>, defaultValue<T>, defaultValue<T>};
}
class S {
public:
S() : DEFAULT_INIT(_arr1), DEFAULT_INIT(_arr2), DEFAULT_INIT(_n) {}
S(unsigned int n) : DEFAULT_INIT(_arr1), DEFAULT_INIT(_arr2), _n{n} {}
private:
Arr1<unsigned int> _arr1;
Arr1<float> _arr2;
unsigned int _n;
};
}
int main(){
return 0;
}
导致汇编错误
/tmp/ccWrYvQ2.s: Assembler messages:
/tmp/ccWrYvQ2.s:110: Error: symbol `_ZN9MyProject12_GLOBAL__N_1L12defaultValueE' is already defined
在玩编译器浏览器时(考虑到其他使用更新版本的gcc编译的CI构建没有问题), 我发现这只会发生在gcc <6.2中,并且是由于编译器为defaultValue<Arr1<T>>
和defaultValue<Arr2<T>>
生成相同的符号。
由于在此项目中,我们仍然希望支持(目前)有错误的操作系统和默认编译器,是否有任何解决方法使其正常工作?