In a bit of serialization code for the project I'm working on, I have a type whose size depends on the compiler. To deal with this, I decided to use a specialized specialization that works great. Everything is allowed at compile time. The code looks a bit like this (not real code, just an example):
template <int size> void special_function() { std::cout << "Called without specialization: " << size << std::endl; } template <> void special_function<4>() { std::cout << "dword" << std::endl; } template <> void special_function<8>() { std::cout << "qword" << std::endl; } int main() { special_function<sizeof(int)>(); return 0; }
On my 32-bit system, executing the above program outputs a dword , as expected. But the whole point is to do it this way, and not just do if (sizeof(int) == 4) { ... } else if ... , so this is what I was hoping the compiler would generate code only for the corresponding function. Since special_function<4> is the only one called in this program, I expected it to be the only compiler generated (gcc 4.1.2 in this case, on x86 Linux).
But this is not observable behavior.
While it really works, the code for each specialized specialization is created, despite the fact that it has never been used. However, a general definition is not generated.
I should mention that this is a one-step compilation, not a compilation of intermediate objects into files, followed by a link. In this case, it would be natural to postpone the removal of dead code to the link stage, and I know that linkers are not always terribly good at this.
Does anyone know what is going on? Is there a subtlety of template specialization that I am missing here? The Lord knows that the devil is in the details with C ++.
EDIT: as mentioned, this happens with both -O3 and -Os.
EDIT2: Rob below suggested including functions in an anonymous namespace. Doing this and compiling with any level of optimization really removes dead code, which is good. But I was curious, so I tried to do the same with the following program:
namespace { void foo() { std::cout << "Foo!" << std::endl; } void bar() { std::cout << "Bar!" << std::endl; } } int main() { foo(); return 0; }
The idea here is to see if Rob's solution is really related to template specialization. As it turned out, the above code compiled with optimizations turned on excludes the unused definition of bar() from the executable. Therefore, it seems that although his answer solves my immediate problem, he does not explain why template specializations that are not used are compiled at all.
Does anyone know about the relevant snippet from the standard that explains this? I always thought that templates are only generated when used, but perhaps this is not the case for full specialization ...