Инициализировать std :: массив Eigen :: Map - PullRequest
2 голосов
/ 23 января 2020

Я пишу интерфейс для некоторых данных std::array<std::array<double,3>,4> a. Я хочу иметь возможность интерпретировать данные как std::array из Eigen::Map<Eigen::Vector3d>. Как я могу инициализировать std::array, если у меня нет инициализатора по умолчанию? По сути, массив должен быть построен до {} в конструкторе.

class Interface{
  Interface( std::array<std::array<double,3>,4>& a ) :
  data_( a[0].data() ), // this works for initializing just the one
  array_of_data_( /* what goes here? */ ) {}
protected:
  Eigen::Map<Eigen::Vector3d> data_;
  std::array<Eigen::Map<Eigen::Vector3d>,4> array_of_data_;
}

пример data_ включен для демонстрации построения одной карты из одной std::array<double,3>.

1 Ответ

5 голосов
/ 23 января 2020

Очевидный способ - просто повторить 4 раза in[index].data(), как все элементы, взятые массивом:

class Interface {
public:
  Interface( std::array<std::array<double,3>,4>& a ) :
   data_( a[0].data() ), // this works for initializing just the one
   array_of_data_{ Eigen::Map<Eigen::Vector3d>(a[0].data()),
    Eigen::Map<Eigen::Vector3d>(a[1].data()),
    Eigen::Map<Eigen::Vector3d>(a[2].data()),
    Eigen::Map<Eigen::Vector3d>(a[3].data()) } 
{}

, но это может быть утомительно, если второе измерение массива будет иметь большее значение.

Вы можете использовать std::index_sequence и упаковать расширения для его сокращения:

template<size_t D1, size_t D2, size_t ... idx>
auto makeMap( 
    std::array< std::array<double,D1>, D2>& in,
    std::index_sequence<idx...> seq) 
{
    return std::array< Eigen::Map<Eigen::Vector3d>,  D2>{
        Eigen::Map<Eigen::Vector3d>(in[idx].data())...
    };
}

template<size_t D1, size_t D2, size_t ... idx>
auto makeMap( std::array< std::array<double,D1>, D2>& in) {
    return makeMap(in, std::make_index_sequence<D2>());
}

Рабочая версия в Compiler Explorer

...