boost — c ++ проверяет вложенную typedef параметра шаблона, чтобы получить его скалярный базовый тип

Рассмотрим экспоненциальный сглаживающий шаблонный класс ниже. Этот класс предназначен для экспоненциального сглаживания / фильтрации последовательных данных (см. Метод обновления). Elemtype может быть вектором, а Floattype обычно является скаляром. Например.

ExponentialSmoother<Eigen::Vector2f, float> x(0.1, Vector2f(0.5, 0.5));

В этом примере можно избежать второго параметра шаблона Floattype, поскольку класс Matrix Eigen содержит вложенную typedef для получения скалярного базового типа:

Vector2f::Scalar

Также целесообразно создавать экземпляры Elemtype и Floatype как float для сглаживания одномерных данных. В этом случае второй шаблонный параметр также может быть пропущен.

template <class Elemtype, class Floattype>
class ExponentialSmoother
{
public:
// ctor
ExponentialSmoother(Floattype alpha, Elemtype& initial_estimate);

// getters
inline const Elemtype& getValue() const {return estimate_;}
inline const Floattype getAlpha() const {return alpha_;}

const Elemtype& update(const Elemtype& curr)
{
estimate_ = (alpha_ * curr) + (((Floattype)1-alpha) * estimate_);
return estimate_;
}

private:
Elemtype estimate_;
Floattype alpha_;  // smoothing factor within [0,1]
}

Теперь мой вопрос: что является «самым элегантным» решением для реализации ExponentialSmoother только с одним параметром шаблона (тип элемента)?
Он должен работать с собственными векторами и матрицами, а также с типами с плавающей точкой.

Другими словами, возможно ли проверить, существует ли Elemtype :: Scalar, и если нет (то есть Elemtype — это float или double), определите Floattype как Elemtype?

Аналогичный вопрос был задан Вот. Но мне интересно, каково наиболее общее решение, если, например, векторы STL также должны поддерживаться. Все ли типы требуют одного и того же вложенного определения типа (или некоторого класса признаков с согласованным именованием)?

5

Решение

Вы можете использовать помощника. Ссылка, которую вы дали, почти содержит решение:

template<class T, class R = void>
struct enable_if_type
{
typedef R type;
};

template<class E, class Enable = void>
struct GetFloatType
{
typedef E type;
};

template<class E>
struct GetFloatType<E, typename enable_if_type<typename E::Scalar>::type>
{
typedef typename E::Scalar type;
};

Тогда в вашем классе:

template <class Elemtype, class Floattype = typename GetFloatType<Elemtype>::type>
class ExponentialSmoother
{
// ...
};

Кроме того, благодаря этому пользователи могут по-прежнему вручную указывать тип своего плавающего элемента. Вы можете видеть это жить. Бонус: работает с C ++ 03 без проблем.

Обратите внимание, что вы можете добавить более частичные специализации GetFloatType, Вот живой пример. Не забудь это ElemType должны быть приемлемы для только один специализация GetFloatTypeили это будет неоднозначно (и приведет к ошибке компиляции).

3

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector