Проверьте целостный тип

0

Как проверить, является ли тип параметра шаблона интегральным?

Я знаю, что для этого я могу использовать std::is_integral<> в C++ 11. Там даже вопрос для этого.

Как проверить, что тип параметра шаблона является неотъемлемым?

Я также знаю, что Boost предоставляет эту функцию. Меня интересует, как "вручную" выполнить эту проверку.

Нет конкретной проблемы, которую я пытаюсь решить. Это абстрактный вопрос о C++.

  • 0
    Возможно, кодовая база Boost могла бы дать этот ответ напрямую? Т.е. прочесывая код, чтобы посмотреть, как это там делается ...
  • 0
    Мне известны два основных способа: либо специализировать их для каждого целочисленного типа, либо составить список типов и просмотреть его.
Показать ещё 1 комментарий
Теги:
templates
typechecking
c++03

3 ответа

4
Лучший ответ

В ручном режиме вы должны сначала определить класс шаблона, который определяет, что во время компиляции значение false:

template<bool B>
struct bool_type {
    static const bool value = B;
};

typedef bool_type<true> true_type;
typedef bool_type<false> false_type;

После этого вы начинаете определять класс признаков со случаями по умолчанию и некоторыми случаями перенаправления:

template<typename T>
struct is_integral : false_type {};

template<typename T>
struct is_integral<const T> : is_integral<T> {};

template<typename T>
struct is_integral<volatile T> : is_integral<T> {};

Тогда ядро его будет создано вручную, создавая экземпляр шаблонной специализации для интегральных типов.

template<>
struct is_integral<int> : true_type {};

template<>
struct is_integral<long> : true_type {};

// etc

Это один из способов сделать это в любом случае. У вас может быть макрос, который автоматически генерирует их, чтобы сделать его проще. Однако основная идея остается прежней, они просто проверяют, является ли конкретный тип частью группы, которую вы запрашиваете, и это делается через какой-то вид. Этот способ (явное создание шаблона), вероятно, самый простой способ сделать это.

  • 0
    Что ж, это, конечно, ответ на вопрос, хотя я надеялся, что был какой-то код, который потерпит неудачу для целочисленного типа, но не для типа с плавающей точкой.
  • 0
    @Praxeolitic Они на самом деле не терпят неудачу - ни одна из черт на самом деле не делает - они возвращают false вместо true для ::value .
Показать ещё 1 комментарий
1

Это может быть ответ "ссылка только", но ИМХО отвечает на вопрос,

Возможная реализация:

Строка с 151 по 256 из GCC 4.8.1 Онлайн-документы

См. Другие typedef также закодированные выше строки 151.

0

Вы можете сделать что-то подобное, чтобы определить, является ли числовой тип интегральным или может иметь дробную часть. Этот код не будет компилироваться с нечисловыми типами, но дальнейшее метапрограммирование может быть добавлено для фильтрации произвольных типов, если это то, что вы хотите. Это также может быть изменено для обеспечения типа "истинного" или "ложного" типа (например, ответа Rapptz) вместо статического значения bool.

Я дал два способа проверить значение (а не тип). Один использует тип decltype для получения типа, а другой использует функцию шаблона. Функция может использоваться, если decltype недоступен, но его результат, вероятно, можно использовать только во время выполнения (constexpr, вероятно, недоступен, если decltype не является).

И чтобы убедиться, что это ясно: макрос VALUE_IS_INTEGER и функция шаблона value_is_integer не проверяют, является ли данное значение целым числом, они проверяют, является ли тип значения интегральным.

#include <iostream>

template <typename T, bool IS_INTEGRAL = T(3)/T(2)<=T(1) || T(3)/T(2)>=T(2)>
   struct IsIntegerTypeCheck {
   static const bool is_integer = IS_INTEGRAL;
};

#define TYPE_IS_INTEGER(type)   (IsIntegerTypeCheck<type>::is_integer)
#define VALUE_IS_INTEGER(value) (IsIntegerTypeCheck<decltype(value)>::is_integer)

template <typename T> static bool value_is_integer(const T& value) {
    return IsIntegerTypeCheck<T>::is_integer; 
}

template <typename ST>
void dump_bool(ST message, bool value) {
    std::cout << message << ' ' << (value ? "true" : "false") << "\n";
}

int main() {
    static const bool   int_is_integer = TYPE_IS_INTEGER(int);
    static const bool   float_is_integer = TYPE_IS_INTEGER(float);
    static const long   unity = 1;
    static const double tau = 3.1415925 * 2;
    static const bool   unity_is_integer = VALUE_IS_INTEGER(unity);
    static const bool   tau_is_integer = value_is_integer(tau);
    dump_bool("int is integer:  ", int_is_integer);
    dump_bool("float is integer:", float_is_integer);
    dump_bool("unity is integer:", unity_is_integer);
    dump_bool("tau is integer:  ", tau_is_integer);
    return 0;
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню