Скопировать аргумент шаблонной функции в Eigen - PullRequest
6 голосов
/ 01 апреля 2019

Я пишу универсальный класс, который использует собственные типы данных.У меня уже есть проблемы с назначением аргументов конструктора для переменных класса.Упрощенная версия моего кода будет выглядеть так:

template <typename Derived>
class A
{
public:
  Eigen::Matrix<Derived> M; // error C2976: too few template parameters

A(const Eigen::DenseBase<Derived> & V)
{
  M = V.eval(); // I would want to snapshot the value of V.
}
};

Мой вопрос сейчас, какой тип данных M должен быть?Я пробовал различные варианты, такие как:

Eigen::internal::plain_matrix_type_column_major<Derived> M;
Eigen::DenseBase<Derived> M;

, но они просто генерируют разные ошибки.Обратите внимание, что я использую C ++ 17 и ожидаю, что параметр шаблона класса будет выведен из конструктора.

Ответы [ 3 ]

4 голосов
/ 01 апреля 2019

Объявление переменной Eigen::Matrix M должно выглядеть примерно так:

Eigen::Matrix<typename Derived::Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> M; 

Тогда ваш код скомпилируется.См. Демо .

Подробное описание каждого из параметров шаблона можно найти по адресу по этой ссылке .

3 голосов
/ 01 апреля 2019

Общий способ объявления вашего типа - использовать объявление, генерирующее его как источник, таким образом, вам не нужно искать конкретные способы объявления сложных типов шаблонов, это пример, основанный на вашем коде:

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;
1 голос
/ 01 апреля 2019

Ваш контейнер нуждается в фактическом "обычном типе" в качестве аргумента шаблона:

template <typename PlainType>
class A
{
    PlainType M; 
public:
    template<class Derived>
    A(const Eigen::MatrixBase<Derived> & V) : M(V) {}
};

И вам нужно дополнительное правило вывода шаблона:

template<class Derived>
A(const Eigen::MatrixBase<Derived> & V) -> A<typename Derived::PlainObject>;

Пример использования ( на кресте ):

template<class X>
void bar(X&); // just to read full type of A

void foo(Eigen::Matrix2d const& M)
{
    A a = M*M;
    bar(a);  // calls bar<A<Matrix2d>>();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...