Look at base::m_visible
method in tps.hpp (it's «default»):
#include <sstream>
#include <iostream>
template <typename T> struct base
{
void m_log() const;
void m_visible() const;
};
struct inheritor: base<inheritor>
{
void log() const;
};
template <typename T> void base<T>::m_log() const
{
std::ostringstream os;
m_visible();
os.str(""); // We have «default/default» if comment here, :-0
std::cout << os.str();
}
template <typename T> void base<T>::m_visible() const
{
std::cout
<< "default" << std::endl
;
}
which specialized for inheritor
struct in tps_spec.cpp (named «spec»):
#include "tps.hpp"
template <> void base<inheritor>::m_visible() const
{
std::cout
<< "spec" << std::endl
;
}
void inheritor::log() const
{
m_log();
}
and further called from tps_main.cpp:
#include "tps.hpp"
int main(int, char **argv)
{
std::cout << argv[0] << ": ";
inheritor().m_log(); // We have «spec/spec» if call inheritor::log
return 0;
}
Result depends on order of compilation units (GCC 4.8.4):
g++ -Wall -O3 -o tps1 tps_spec.cpp tps_main.cpp && g++ -Wall -O3 -o tps2 tps_main.cpp tps_spec.cpp && ./tps1 ; ./tps2
./tps1: spec
./tps2: default
and this happens only with optimization -O3
. Any experimental editions, marked by comments yields different results. Why?