Search code examples
c++eigenstdtuple

Can I concatenate a std::tuple of Eigen::Vectors?


If I have a std::tuple of statically allocated Eigen::Vectors (from the popular Eigen library), for example

std::tuple<Eigen::Vector2f, Eigen::Vector3f, Eigen::Vector2f>

Is there a way I can turn this into a single Eigen::Vector7f (i.e., Eigen::Matrix<float, 7, 1>) of the three vectors concatenated? It feels like I should be able to do this at compile time, given that the sizes and types of everything are known.


Solution

  • You can write:

    template<int R1, int R2, int R3>
    auto foo(std::tuple< 
        Eigen::Matrix<float,R1,1>, 
        Eigen::Matrix<float,R2,1>, 
        Eigen::Matrix<float,R3,1> > t)
    {
        Eigen::Matrix<float,R1+R2+R3,1> res;
        res.template block<R1,1>(0,0) = std::get<0>(t);
        res.template block<R2,1>(R1,0) = std::get<1>(t);
        res.template block<R3,1>(R1+R2,0) = std::get<2>(t);
        return res;
    }
    
    int main() {
        Eigen::Vector2f v1;
        v1 << 1,2;
        Eigen::Vector3f v2;
        v2 << 3,4,5;
        std::cout << foo(std::make_tuple(v1,v2,v1)) << std::endl;
    

    as output:

    1,2,3,4,5,1,2

    Live demo


    Below is more generic version taking multiple vectors as tuple components:

    template<class RES, int ... R, size_t ... Indices>
    void concatenateHelper(RES& res, 
        const std::tuple< Eigen::Matrix<float,R,1>... >& t,
        std::index_sequence<Indices...>)
    {
        int idx = 0;
        int fakeArray [] = {(res.template block<R,1>(idx,0) = std::get<Indices>(t),idx += R,0)...};
        static_cast<void>(fakeArray);
    }
    
    template<int ... R>
    auto concatenate(const std::tuple< Eigen::Matrix<float,R,1> ... >& t) 
    {
        Eigen::Matrix<float, (R + ...),1> res;
        concatenateHelper(res,t,std::make_index_sequence<sizeof...(R)>{});
        return res;
    }
    

    Demo