I have a templated class, and I am trying to create a stringifier for a nested enum.
I can get it compiling and working if I inline the operator<<
code directly into the body of the class, but I'm trying to put it in a separate impl.hpp
file, for legibility.
But, I can't get it to compile. It seems like it should be possible, but I'm stumbling on the syntax C++ requires...
Here's a small example that demonstrates the problem, along with a live link: https://godbolt.org/z/6cMn8Gf14
#include <iostream>
using std::cout;
using std::endl;
template <class T>
struct Foo {
enum class State {
X,Y,Z
};
// This version works OK:
/*
friend std::ostream& operator<<(std::ostream &os, State s) {
return os << "stringify state...";
}
*/
// This version fails - see full error down in main().
template <class T2>
friend std::ostream& operator<<(std::ostream &os, typename Foo<T2>::State s);
};
template <class T>
std::ostream& operator<<(std::ostream &os, typename Foo<T>::State s) {
return os << "stringify state...";
}
int main()
{
auto x = Foo<int>::State::X;
/*
Error: no match for 'operator<<' ...
Details:
note: candidate: 'template<class T> std::ostream& operator<<(std::ostream&, typename Foo<T>::State)'
std::ostream& operator<<(std::ostream &os, typename Foo<T>::State s) {
^~~~~~~~
note: template argument deduction/substitution failed:
note: couldn't deduce template parameter 'T'
cout << "X: " << x << endl;
^
*/
cout << "X: " << x << endl;
return 0;
}
How should this be written?