I have a template struct Foo
that defines an inner struct Bar
.
Now, I would like to overload the stream operator <<
for this inner struct Bar
, but the compiler seems to ignore my overload implementation:
error: no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘Foo<3>::Bar’)
My code is the following:
#include <iostream>
//////////////////////////////////////////////////////////////////////////////////////////
template<int N>
struct Foo
{
struct Bar {};
};
//////////////////////////////////////////////////////////////////////////////////////////
template<int N>
std::ostream& operator<< (std::ostream& os, const typename Foo<N>::Bar& x)
{
return os;
}
//////////////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
Foo<3>::Bar x;
std::cout << x << std::endl;
}
I can't see the (maybe obvious) error.
Question Is it possible to overload an operator of an inner structure that belongs to a template class?
Yes, like this:
#include <iostream>
template<int N>
struct Foo
{
struct Bar {
friend std::ostream& operator<<(std::ostream& os,const Bar&) { return os;}
};
};
int main (int argc, char** argv)
{
Foo<3>::Bar x;
std::cout << x << std::endl;
}
In your code the operator<<
is not actually wrong. Its just impossible to deduce N
from Foo<N>::Bar
. You can only call it by making N
explicit:
int main (int argc, char** argv)
{
Foo<3>::Bar x;
operator<<<3>(std::cout,x);
}
The reason is that Foo<N>::Bar
is a non deduced context. See What is a non-deduced context? for more details. In a nutshell, the reason why this does not work is that there is no 1:1 relation between Foo<N>::Bar
and N
. Consider you add a specialization:
template <> struct Foo<42> {
using Bar = Foo<3>::Bar;
};
Now Foo<42>::Bar
and Foo<3>::Bar
refer to exactly the same type. This
Foo<3>::Bar x;
std::cout << x;
and this
Foo<42>::Bar x;
std::cout << x;
would have to deduce different values for N
but in both examples x
is of exactly the same type.