I'm using GCC 8.1.0 / binutils 2.30 (I plan to upgrade to latest stuff
in the next few weeks or so...), on GNU/Linux Intel 64bit.
I have a templated class C that required its type T to have operator
bool() defined in order to work properly.
I want to use that with a enum class so clearly that doesn't work for
me. However I had an idea: I changed the implementation of the
templated class so that instead of "if (t)" it uses "if (!!t)" then I
created an operator!(T).
I made it static inline like this:
static inline bool operator!(T t) { return t != T::EMPTY; }
When I compile "normally" this all works fantastically.
But, when I compile using a "unity" build, I'm getting multiple
definition errors:
ld: error: libFoo.a(unity_2.cxx.o): multiple definition of 'operator!(T)'
ld: libFoo.a(unity_12.cxx.o): previous definition here
If you're not familiar with "unity" builds basically the build system
will generate a meta-source file (above called things like unity_2.cxx
or unity_12.cxx etc.) and compile that: the only thing in the meta-
source file are includes of other source files:
#include "File1.cpp"
#include "File2.cpp"
...
The goal is to improve compile times (at the expense of compiling more
stuff when something changes obviously).
I don't understand why I'm getting multiple definition errors.
And it gets even stranger: when I nm my library, sure enough I see:
libFoo.a:unity_12.cxx.o:0000000000003ef0 T operator!(T)
libFoo.a:unity_9.cxx.o:0000000000003190 T operator!(T)
libFoo.a:unity_8.cxx.o:0000000000003640 T operator!(T)
libFoo.a:unity_2.cxx.o:0000000000005d80 T operator!(T)
But!! When I nm the individual cxx.o files none of these operator
symbols appear, at all!
It's like they were created by the ar command, which is just:
ar qc libFoo.a ....
Which seems bizarre to me. Is this a bug in ... something ... either
the compiler or binutils? Or, is my trick above not valid for some
reason?