Шаблон C ++ - оценивает статический встроенный метод внутри шаблона и передает результат в качестве аргумента типа шаблона - PullRequest
0 голосов
/ 02 марта 2019

У меня есть шаблон, который принимает 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;
}

1 Ответ

0 голосов
/ 02 марта 2019

Ваша основная проблема заключается в этой строке:

typedef SELECT<-32768 < F::eval(X) && F::eval(X) < 32767> result;

это должно быть:

typedef typename SELECT < -32768 < F::eval(X) && F::eval(X) < 32767 > ::type result;

ПРИМЕЧАНИЕ: конечный ":: type" фактически указывает на тип из ваших структур SELECTи ведущее "typename", так как это зависимый тип.

Ниже рабочая версия.Обратите внимание, что я также немного изменил SELECT, но это не требуется для компиляции.

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;
};

struct myS
{
    static constexpr double eval(double x) { return x; }
};

int main()
{
    std::cout << typeid(DEDUCTOR<myS, 100>::result).name() << std::endl;
    std::cout << typeid(DEDUCTOR<myS, 100000>::result).name() << std::endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...