У меня есть шаблон, который принимает class F
и int X
.Класс F имеет метод static inline double eval(double x)
.Исходя из результата, возвращаемого eval
, мне нужно выбрать между int
и long
типами - наименьший возможный, который будет соответствовать результату (преобразованный в круглое число, если он удвоен).
Я пытался сделатьэто так, но я получаю Non-type template argument is not a constant expression
ошибку.
template <class F, int X>
struct DEDUCTOR {
typedef SELECT<-32768 < F::eval(X) && F::eval(X) < 32767> result;
}
где SELECT
определяется следующим образом:
template <bool is_int>
struct SELECT {};
template <>
struct SELECT<true> {
typedef int type;
};
template <>
struct SELECT<false> {
typedef long type;
};
Есть ли способ создать такой шаблон?
============================ ОБНОВЛЕНИЕ:
Согласно совету, я добавил constexpr в eval
функция.Это работает сейчас, но сейчас всегда.Полный пример:
#include <iostream>
#include <math.h>
#include <typeinfo>
struct X {
static constexpr double eval(double x) { return x; };
};
template<class L, class R>
struct MULT {
static constexpr double eval(double x) {
return L::eval(x) * R::eval(x);
}
};
template<class L, class R>
struct DIV {
static constexpr double eval(double x) {
return L::eval(x) / R::eval(x);
}
};
template <bool is_int>
struct SELECT {
typedef long type;
};
template <>
struct SELECT<true> {
typedef int type;
};
template<class F, int X>
struct DEDUCTOR {
typedef typename SELECT<-32768 < F::eval(X) && F::eval(X) < 32767>::type result;
};
int main() {
// typedef MULT<MULT<X, X>, X> F; // works
typedef DIV<DIV<X, X>, X> F; // doesn't work
typedef DEDUCTOR<F, 0> deductor;
std::cout << typeid(deductor::result).name() << std::endl;
return 0;
}