Общий способ объявления вашего типа - использовать объявление, генерирующее его как источник, таким образом, вам не нужно искать конкретные способы объявления сложных типов шаблонов, это пример, основанный на вашем коде:
decltype(static_cast<Eigen::DenseBase<Derived> *>(nullptr)->eval()) M;
не волнуйтесь, здесь нет разыменования nullptr, потому что код внутри decltype не выполняется.
Как указано в комментариях, есть более чистый способ написания этого:
decltype(declval<Eigen::DenseBase<Derived>>().eval()) M;
и если вы беспокоитесь о том, что тип может быть ссылкой, и не хотите этого:
remove_reference_t<decltype(declval<Eigen::DenseBase<Derived>>().eval())> M;
также не забудьте #include <type_traits>
и либо префиксировать все с помощью std::
или добавьте using namespace std;
к вашему коду.
Чтобы упростить синтаксис для будущего использования, добавьте это в начало вашего кода:
template<typename T, typename T::f>
using member_function_return_t = remove_reference_t<decltype(declval<T>().f())>;
и затем объявите переменную как:
member_function_return_t<Eigen::DenseBase<Derived>, Eigen::DenseBase<Derived>::eval> M;