This is pretty messy, since Derived
isn't complete when template argument deduction happens for Base
. I assume the obvious answer - pass Vector
and Scalar
explicitly - is unsatisfactory. How about:
template <template <class, class> class Derived,
class Vector, class Scalar>
struct Base {};
template <class Vector, class Scalar>
struct Derived : Base<Derived, Vector, Scalar> {};
Why the strange restriction to not use typedef
? I find:
template <class Vector>
using ScalarTypeOf =
typename std::decay<decltype(std::declval<Vector>()[0])>::type;
template <class Crtp>
using VectorTypeOf =
typename std::decay<decltype(std::declval<Crtp>().data())>::type;
template <class Crtp>
struct Base {
using Vector = VectorTypeOf<Crtp>;
using Scalar = ScalarTypeOf<Vector>;
};
template <class Vector>
struct Derived : public Base<Derived<Vector>> {
using Scalar = ScalarTypeOf<Vector>;
};
to be a bit more readable.