Question

Consider the following code:

#include <iostream>

template<class T>
struct outer {
    struct inner {};
};

template<class T>
std::ostream& operator<<(std::ostream & stream, 
                         typename outer<T>::inner const& value) {
    std::cout << "An outer::inner!";
    return stream;
}

int main() {
    outer<float>::inner foo;

    std::cout << foo << std::endl; // does not compile
}

This does not compile, because typename outer<T>::inner is a nondeduced context (as explained here), meaning the template-argument-type cannot be deduced by the compiler (read this answer for the why). As I see it, I have two options to make it work:

  1. Move inner outside of outer and make it a class-template. I prefer this one, because the impact on the using code is smaller.
  2. Add a to_string-method to inner.

Are there any other solutions for this (that do not result in ugly syntax in the using code)?

Was it helpful?

Solution

You can move the operator into the inner class body and put friend before it. Then replace the parameter type by just inner.

Another technique is to derive inner from a CRTP base parameterized by inner. Then make the parameter type the CRTP class and cast the parameter reference to the derived inner class, the type of which is given by the template argument you deduce.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top