El operador amigo en clase no parece participar en la resolución de sobrecarga

Mientras escribe una plantilla CRTP que permite a las clases proporcionar sobrecargas paraoperator+ basado en argumentos de plantilla, descubrí que un operador amigo en clase no parece participar en la resolución de sobrecarga si ninguno de sus argumentos es del tipo de la clase en la que se definió.

Reducía:

enum class FooValueT{
    zero, one, two
};

class Foo{
    FooValueT val_;
public:
    Foo(FooValueT x) : val_(x){};

    Foo& operator+=(Foo other){
        val_ = (FooValueT)((int)val_ + (int)other.val_);
        return *this;
    }

    //overload for Foo+Foo, FooValueT+Foo and Foo+FooValueT
    friend Foo operator+(Foo lhs, Foo rhs){
        Foo ret = lhs;
        return ret += lhs;
    }

    //explicit overload for FooValueT+FooValueT
    friend Foo operator+(FooValueT lhs, FooValueT rhs){
        return (Foo)lhs + (Foo)rhs;
    }
};

Parece un poco excesivo, pero es necesario ya queFoo my = FooValueT::one + FooValueT::zero; debe ser una expresión válida y si ninguno de los argumentos tiene un tipo de clase, no se convierten implícitamente, como se explica enesta respuesta a una pregunta anterior mía.

A pesar de todo este esfuerzo, el siguiente código no se compila:

int main(int argc, char* argv[])
{
    Foo my = FooValueT::zero;
    my += FooValueT::one;
    my = Foo(FooValueT::zero) + FooValueT::two;
    my = FooValueT::zero + Foo(FooValueT::two);
    my = FooValueT::zero + FooValueT::two; //error C2676
    return 0;
}

El mensaje de error es:

error C2676: binary '+' : 'FooValueT' does not define this operator or a conversion to a type acceptable to the predefined operator

Este problema se resuelve una vez que muevo el operador fuera de la clase por completo o lo declaro como amigo pero lo defino fuera de la clase. Ninguno de los dos parece ser una opción viable cuandoFoo es una clase de plantilla de la que se derivará.

Hasta donde yo sé, la definición de amigo en clase anterior deoperator+(ValueT,ValueT) debería crear una función libre, tal como lo haría esta definición:

class Foo{
/*All the stuff you saw previously*/
    friend Foo operator+(FooValueT lhs, FooValueT rhs);
};

Foo operator+(FooValueT lhs, FooValueT rhs){
    return (Foo)lhs + (Foo)rhs;
}

¿Dónde me estoy equivocando aquí? ¿La definición de funciones de amigo en clase cambia las reglas de resolución de sobrecarga en comparación con las funciones de amigo gratuitas normales?

Respuestas a la pregunta(1)

Su respuesta a la pregunta