CRTP с базовым классом, пытающийся получить тип возврата члена производного класса: недопустимое использование неполного типа

Рассмотрим следующий код (это только для примера):

#include <iostream>
#include <type_traits>
#include <array>

template <
class Crtp,
class Vector = typename std::decay<decltype(std::declval<Crtp>().data())>::type,
class Scalar = typename std::decay<decltype(std::declval<Crtp>().data(0))>::type
>
struct Base
{;};

template <
class Vector = std::array<double, 3>,
class Scalar = typename std::decay<decltype(std::declval<Vector>()[0])>::type
>
struct Derived
: public Base<Derived<Vector, Scalar>>
{
Vector _data;
inline Vector& data() {return _data;}
inline const Vector& data() const {return _data;}
inline Scalar& data(const unsigned int i) {return _data[i];}
inline const Scalar& data(const unsigned int i) const {return _data[i];}
};

int main()
{
Derived<> d;
return 0;
}

Возвращает следующую ошибку:

main.cpp: In instantiation of 'struct Derived<>':
main.cpp:28:14: required from here
main.cpp:16:8: error: invalid use of incomplete type 'struct Derived<>'
main.cpp:16:8: error: declaration of 'struct Derived<>'

Есть ли способ решить эту проблему (без использования typedefs и только с помощью шаблонов)?

4

Решение

Это довольно грязно, так как Derived не завершено, когда вывод аргумента шаблона происходит для Base, Я предполагаю очевидный ответ — пройти Vector а также Scalar явно — неудовлетворительно. Как насчет:

template <template <class, class> class Derived,
class Vector, class Scalar>
struct Base {};

template <class Vector, class Scalar>
struct Derived : Base<Derived, Vector, Scalar> {};

Почему странное ограничение не использовать typedef? Я нахожу:

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>;
};

быть немного более читабельным.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]