Search code examples
c++templatestype-inferenceargument-dependent-lookup

I am having trouble with a simple argument dependent lookup / template type inferencing issue


I have this snippet of code and I do not understand why the std::cout line is not compiling... The argument lookup / template argument inferencing seems correct...

#include <iostream>

template<typename T>
struct A
{
    struct M1
    {
        T x;
    };
};

template<typename T>
std::ostream &operator<<(std::ostream &os, typename A<T>::M1 const &o)
{
    os << o.x;
    return os;
}


int main()
{
    A<int>::M1 a;

    std::cout << a; // This line fails

    return 0;
}

BTW I'm trying to do this without a declaring operator<<() as an inline function.


Solution

  • Your problem is that T is in a non deduced context. C++ will only simple pattern match, it will not invert possibly arbitrary type maps.

    Imagine there was a specialization of A<void> that set using M1=A<int>::M1. Now both int and void are valid T for your <<. As the problem is intractible in general, C++ refuses to even try: you can only pattern match on direct template arguments of your argument types.

    To do what you really want:

    template<typename T>
    struct A {
      struct M1 {
        T x;
        friend std::ostream& operator<<(std::ostream& os, M1 const& m1){
          return os << m1.x;
        }
      };
    };
    

    Learn to love Koenig operators.