Как проверить, является ли тип параметра шаблона интегральным?
Я знаю, что для этого я могу использовать std::is_integral<>
в C++ 11. Там даже вопрос для этого.
Как проверить, что тип параметра шаблона является неотъемлемым?
Я также знаю, что Boost предоставляет эту функцию. Меня интересует, как "вручную" выполнить эту проверку.
Нет конкретной проблемы, которую я пытаюсь решить. Это абстрактный вопрос о C++.
В ручном режиме вы должны сначала определить класс шаблона, который определяет, что во время компиляции значение 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
Это один из способов сделать это в любом случае. У вас может быть макрос, который автоматически генерирует их, чтобы сделать его проще. Однако основная идея остается прежней, они просто проверяют, является ли конкретный тип частью группы, которую вы запрашиваете, и это делается через какой-то вид. Этот способ (явное создание шаблона), вероятно, самый простой способ сделать это.
false
вместо true
для ::value
.
Это может быть ответ "ссылка только", но ИМХО отвечает на вопрос,
Возможная реализация:
Строка с 151 по 256
из GCC 4.8.1 Онлайн-документы
См. Другие typedef
также закодированные выше строки 151.
Вы можете сделать что-то подобное, чтобы определить, является ли числовой тип интегральным или может иметь дробную часть. Этот код не будет компилироваться с нечисловыми типами, но дальнейшее метапрограммирование может быть добавлено для фильтрации произвольных типов, если это то, что вы хотите. Это также может быть изменено для обеспечения типа "истинного" или "ложного" типа (например, ответа 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;
}