I'm not exactly sure why the compiler is unable to infer the proper type here. There is a workaround. Instead of specifying "typename A<T>::B&" as the type, just use "T&".
But you say, "This will cause the operator to be invoked for EVERY type T, not just those of form A<X>::B." Correct. So we need to use some template instantiation rules to prevent that from happening. In this case, SFINAE, "Specialization failure is not an error."
You can do this by adding a special member to the B structure which indicates that it is, in fact, of type A<X>::B. Let's make a bogus class called I_Am_A_B:
Code:
struct I_Am_A_B { };
Then place an instance of this class inside the B struct:
Code:
template <typename T>
struct A
{
struct B { T t; I_Am_A_B i_am_a_b; }
B b;
};
template <typename T>
std::ostream& operator<<(std::ostream& os, const T& b)
{
return os<<"an instance of B";
// PREVENT INSTANTIATION OF THIS TEMPLATE IF T IS NOT A A<X>::B TYPE.
b.i_am_a_b;
}
Does that look awful? That's because it is. But it's the only way I could make it work (aside from the friend method someone else found).