As I've said... nevermind; just read the post again. Specifically this isn't an ODR violation because the relevant type is not in the relevant scope of the relevant template class and the relevant reference is not dependent on any name of the relevant template class. If compilers referenced the "anonymous" 'namespace' directly this would not compile. If linkers understood templates better this would not link.
I'll just take further response simply with: "Paragraph 5 is interesting."
Paragraph 3.2.5 of the standard doesn't apply to "private" definitions, fully specialized templates, or non-dependent template names that aren't in the enclosing scope.
Also, I'm about to start playing "Oblivion". Now, I'll be checking back in a bit, but if the only thing offered is "OMG. YOUR THE WRONG!" don't expect me to take time to respond. I will not take time to respond to repeats either. You're obviously free to disagree again; I wouldn't hold that against you. I just will not take time to respond with repeats of my own. I'm willing to be proven wrong, but it would have to be a different and unfamiliar part of the standard. Basically unless you can show that differing fully specialized templates and "private" definitions are both in violation of the ODR and/or undefined behavior then you shouldn't bother.
If you actually instantiate a given template with a "private" type, manually telling the compiler that the instantiation will be modeled on a private type, then everything is fine.
I had just turned on my XBox 360 when I thought of a problem. That seems as if I'm saying the relevant type must be a "private" type, but that isn't the case. I thought I would clear it up. You don't have to change anything relevant to allow the source to run correctly; you only need to make sure the template is mangled as "private". The code provided should be a sufficient demonstration; you only need to change which line is commented out.
Soma
Code:
#include <iostream>
#if defined(__GNUC__)
#include <cxxabi.h>
#endif
template
<
typename type_F
>
struct base
{
virtual void go() = 0;
};
namespace
{
template
<
typename type_F
>
struct derived: public base<type_F>
{
virtual void go()
{
std::cout << __FILE__ << '\n';
}
};
struct i_am_private{};
}
template
<
typename type_F,
typename type2
>
struct holder
{
holder()
{
p = new derived<type_F>;
}
~holder()
{
delete p;
}
void go()
{
#if defined(__GNUC__)
int status(0);
std::cout << abi::__cxa_demangle(typeid(*p).name(), 0, 0, &status) << ':';
#endif
#if !defined(__GNUC__)
std::cout << typeid(*p).name() << ':';
#endif
p->go();
}
base<type_F> * p;
};
void test_a()
{
std::cout << "Test A:";
holder<int, float> h;
//holder<int, i_am_private> h;
h.go();
}
Code:
#include <iostream>
#if defined(__GNUC__)
#include <cxxabi.h>
#endif
template
<
typename type_F
>
struct base
{
virtual void go() = 0;
};
namespace
{
template
<
typename type_F
>
struct derived: public base<type_F>
{
virtual void go()
{
std::cout << __FILE__ << '\n';
}
};
struct i_am_private{};
}
template
<
typename type_F,
typename type2
>
struct holder
{
holder()
{
p = new derived<type_F>;
}
~holder()
{
delete p;
}
void go()
{
#if defined(__GNUC__)
int status(0);
std::cout << abi::__cxa_demangle(typeid(*p).name(), 0, 0, &status) << ':';
#endif
#if !defined(__GNUC__)
std::cout << typeid(*p).name() << ':';
#endif
p->go();
}
base<type_F> * p;
};
void test_b()
{
std::cout << "Test B:";
holder<int, float> h;
//holder<int, i_am_private> h;
h.go();
}