How to overload free function for member type of template

c++, c++03, overloading, templates

Solution

What you have there is a so-called non-deducible context. How could `Value` ever be deduced? You can partially specialize class templates, making it practically impossible for the compiler to even try and test every possible instantiation (of which there are.. well, infinite).

There are two workarounds: Take `Inner` out of `Outer`, or make `operator<<` an inline friend. The latter is the usual way people go.

template<class T>
struct Outer{
  struct Inner{
    T value;
    friend std::ostream& operator<<(std::ostream& os, Inner const& v){
      return os << v.value:
    }
  };
  // ...
};

Problem

I have a template class that defines some member types. It's similar to how `std::map` defines it's `value_type` based on it's own template arguments, but in my case the type is more complex, so it's defined as nested class. Now for debugging I would like to define `operator<<` for that type. But the compiler tells me it can't deduce the template parameters of the outer template. My real code is not contrived like the following example, but this contrived example demonstrates the approach I tried and how it fails: ``` #include <iostream> template <typename Value> class Outer; template <typename Value> std::ostream &operator<<(std::ostream &, const typename Outer<Value>::Inner &); template <typename Value> class Outer { public: struct Inner { Value x; }; void PrintSomething(Value v) { // the real program does something useful with the inner class, of course Inner inner = { v }; std::cout << "Inner = " << inner << std::endl; // <---- THIS SAYS IT CAN'T FIND operator<< }; }; template <typename Value> std::ostream &operator<<(std::ostream &s, const typename Outer<Value>::Inner &v) { return s << v.x; } int main() { Outer<int> o; o.PrintSomething(42); return 0; } ``` This is complete sample to reproduce the problem. The compiler (I've tried 3 of them) says there is no overload of `operator<<` that would take second argument of type `Outer<int>::Inner`. When I try the same thing with different function that does not have other overloads, it instead says `C2783: could not deduce template argument for 'identifier'`, gcc and clang keep saying there is no overload that takes second argument `Outer<int>::Inner`). So is there a way to define `operator<<` taking `Outer<Value>::Inner` for any `Value` as it's right (so it can't be defined as member) argument? Note: I need it to compile in several compilers and some of them don't have any C++11 features, so I need it to be C++03.

Original source