I have come across a strange error in the CI build of a project I'm working in. This only happens on a relatively old OS (Ubuntu 16.04) with a not-so-recent compiler (gcc 5.4.0).
The code causing the error is similar to the following: (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;
}
which results in an assembler error
/tmp/ccWrYvQ2.s: Assembler messages:
/tmp/ccWrYvQ2.s:110: Error: symbol `_ZN9MyProject12_GLOBAL__N_1L12defaultValueE' is already defined
Playing around with compiler explorer (and given that other CI builds with more recent versions of gcc compile without problems) I've seen that this happens only for gcc < 6.2 and that it is due to the compiler generating the same symbol for both defaultValue<Arr1<T>> and defaultValue<Arr2<T>>.
Since in this project we still want to support (for now) the faulty OS with its default compiler, is there any workaround to get this to properly work?