Search code examples
c++templateseigen

C++ Eigen Vector infer vector size at compile time for class


I'm trying to make a wrapper class for Eigen::Matrix. It should take in a pointer to a static size eigen vector (matrix with 1 row), and should return a copy when the getValue() function is called. This is what I currently have

template<std::size_t N>
class InputV
{
public:

    InputV(const Eigen::Matrix<double, N, 1>* in) : in_(in)
    {

    }

    Eigen::Matrix<double, N, 1>
    getValue() const
    {
        return *in_;
    }

private:
    const Eigen::Matrix<double, N, 1>* in_;
};

TEST_CASE("dummy")
{
    Eigen::Matrix<double, 10, 1> a;
    
    InputV<10> in(&a);
}

However, I need to explicitly tell it the size twice, once during the initialization of the source pointer, a second time when creating the InputV wrapper class. Is there a way to have the InputV infer the size N, so I don't have to specify it twice?

Thanks!


Solution

  • If you're using C++17, you can use class template argument deduction (and deduction guides, but you don't need them in this case):

    Eigen::Matrix<double, 10, 1> a;
    
    auto x = InputV(&a);
    InputV y(&a);
    

    If you're using an older C++ version (i.e. C++11 or C++14), you can use a helper function. This works because functions can deduce template arguments in all C++ versions:

    template <std::size_t N>
    InputV<N> makeInputV (Eigen::Matrix<double, N, 1> const * m) {
      return InputV<N>(m);
    }
    
    Eigen::Matrix<double, 10, 1> a;
    auto x = makeInputV(&a);
    

    Live example: https://godbolt.org/z/GqT936

    Edit: Kind of a pet peeve: if it doesn't make sense to pass in a nullptr as argument to your class, then don't allow it. The signature of your InputV constructor tells me passing in an Eigen::Matrix is optional, and that passing in nullptr is perfectly fine.

    If that's not the case, make your code such that something has to be passed in: InputV (Eigen::Matrix<double, N, 1> const &). I.e. use a reference instead of a pointer.

    The much inferior solution is documenting that you shouldn't pass in nullptr (and keeping the documentation up to date, and making sure whoever uses the code reads it, and ...). But why allow it to happen in the first place?

    Rant over :).