2

I am writing an interface to some data std::array<std::array<double,3>,4> a. I want to be able to interpret the data as a std::array of Eigen::Map<Eigen::Vector3d>. How can I initialize the std::array given I do not have a default initializer? Basically the array must be built before {} in the constructor.

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

the example data_ is included to demonstrate the construction of one map from a single std::array<double,3>.

1 Answers1

5

The obvious way is to just repeat 4 times in[index].data() as all elements taken by array:

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()) } 
{}

but it may be tedious if the second dimension of array had greater value.

You could use std::index_sequence and pack expansions to shorten it:

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

Working version on Compiler Explorer

rafix07
  • 20,001
  • 3
  • 20
  • 33