Ziyang
Ziyang

Reputation: 45

Writing templated functions for Eigen and std::vectors

I wish to write a templated function to accept both Eigen::VectorX* (float/int/double) and std::vector<*> (float/int/double) and "simple" int/float/double.

How do i declare the template? The following doesn't work.

// header.h

//std::vector function
template <typename T, typename A>
void do_something(std::vector<T, A> &stdvec)
{
    //do stuff with std::vector<T>
    //e.g. std::fill(stdvec.begin(),stdvec.end(),0);
}

//Eigen vector function
template <typename Derived>
void do_something(Eigen::EigenBase<Derived> &evec)
{
    //do stuff with Eigen::VectorX
    //e.g. evec.setZero()
}

//single value function
template <typename T>
void do_something(T &var)
{
    //do stuff with int/float/double
    //e.g. var = 0;
}

The rationale is to not write individual functions all the different combinations.

Upvotes: 1

Views: 670

Answers (3)

ggael
ggael

Reputation: 29255

You can use std::enable_if to enable the fully generic version for arithmetic types only:

template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value,void>::type
do_something(T &var) { ... }

Upvotes: 1

user2658323
user2658323

Reputation: 553

The trick is not to write several functions (as you discovered), but to apply the scalar function (void do_something(T &var)) differently depending on the container:

Scalar:

do_something(var);

std::vector

std::transform(v.begin(), v.end(), v.begin(), do_something);

Eigen

matrix.unaryExpr(do_something);

Upvotes: 0

chtz
chtz

Reputation: 18827

Eigen::VectorX* only inherits from Eigen::EigenBase<Derived>, so C++ will prefer the do_something(T &var) method. You can declare the Eigen variant of your function as:

template<typename Scalar>
void do_something(Eigen::Matrix<Scalar, Eigen::Dynamic, 1> &evec) { /*...*/}

Upvotes: 0

Related Questions