Depending on whether I compile with -O3 or without optimization the compiler does not select the same function-template-instanciation. Using gcc (Debian 8.3.0-6) 8.3.0.
Due to an oversight I have a default implementation in a function template declaration:
#pragma once
#include <iostream>
template <int>
void func() { std::cerr << "default impl\n"; } // normally no impl here
And their specialisations:
#include "func.h"
template <>
void func<1>()
{
std::cerr << "special 1\n";
}
template <>
void func<2>()
{
std::cerr << "special 2\n";
}
And the main-function.
#include "func.h"
int main(void)
{
func<1>();
func<2>();
return 0;
}
Compiling and running g++ -Wall func.cpp main.cpp -o main && ./main
gives:
special 1
special 2
Using optimizations g++ -O3 -Wall func.cpp main.cpp -o main && ./main
gives:
default impl
default impl
Is this expected? Is the code triggering an unexpected behavior I'm not aware of?
Thanks to @NathanOliver from the comments who made a Wandbox. Compiling with or without optimizations shows the different output.
Your code is ill-formed, no diagnostic required. So different behaviors at different optimization levels are possible.
[temp.expl.spec]
6 If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required. An implicit instantiation is never generated for an explicit specialization that is declared but not defined.
The function template is specialized in one TU, but the other doesn't have a specialization declaration available. It's quite likely an aggressive optimizer chooses the implicit instantiation (that is available inline) instead of finding the one you created elsewhere. The solution is to declare that your specialization exists in the header.