Если сделать в интернет поиск по ключевому слову
is_bool, то вы получите множество ссылок на сайты, связанные с языком программирования
PHP. Эта функция возвращает значение
true, если ее аргумент имеет булевый или, по-другому, логический тип.
Естественно было бы ожидать, что такая же функция имеется в стандарте С++ в заголовочном файле
<type_traits>. Но, увы, такой функции в стандарте С++ нет.
Сначала поставим вопрос, а нужна ли такая функция в стандарте в С++?
Хотя тип
bool относится к целочисленным типам, это особый тип, отличающийся от других целочисленных типов, так как для него не имеет смысла выполнение многих арифметических операций таких, как, к примеру, деление или взятие остатка от деления. Поэтому, когда создается шаблонный класс, который в качестве параметра шаблона должен иметь целочисленный тип и выполнять операции над объектами этого типа, то тип
bool обычно исключается из числа допустимых типов для специализации такого класса.
Для этого используется объявление
static_assert, в котором проверяется аргумент шаблона.
Итак, если, допустим, необходимо, чтобы шаблонный класс принимал в качестве аргумента шаблона только целочисленный тип за исключением типа
bool, и чтобы такая проверка была выполнена на этапе компиляции, то можно воспользоваться двумя классами характеристик из библиотеки
<type_traits>. Первый класс характеристик будет определять, является ли аргумент шаблона целочисленным, а второй класс характеристик будет проверять, является ли он при этом типом
bool, и если является таковым, то компилятор должен выдать сообщение об ошибке.
Вот эти два класса характеристик:
std::is_integral и
std::is_same.
Тогда условие проверки для шаблонного аргумента в объявлении
static_assert может выглядеть следующим образом:
static_assert( std::is_integral<T>::value && !std::is_same<T, bool>::value,
"An integral type other than bool is required for "
"the template argument of the class" );
Если пользователь класса по ошибке попытается использовать этот класс с типом аргумента шаблона
bool, то он получит сообщение об ошибке компилятора, в котором будет присутствовать текст
цитата: |
An integral type other than bool is required for the template argument of the class |
|
Показаннное объявление
static_assert полностью решает проблему проверки типа аргумента шаблона по исключению из допустимых значений типа
bool.
Однако запись
std::is_same<T, bool>::value менее выразительна по сравнению с эквивалентной записью
std::is_bool<Tl>::value, при условии, что такая характеристика типа присутствовала бы в стандарте С++. Имя
is_bool понятно программистам, даже не знающим языка С++, тем более, что это имя хорошо известно, как я указал в самом начале темы, в языке программирования
PHP.
Как сделать так, чтобы использовать это привычное имя вместо записи
std::is_same<T, bool>?
Для этого можно объявить шаблонный алиас типа. Выглядеть он может следующим образом:
template <typename T>
using is_bool = std::is_same<T, bool>;
Теперь предыдущее объявление
static_assert можно переписать в виде:
static_assert( std::is_integral<T>::value && !is_bool<T>::value,
"An integral type other than bool is required for "
"the template argument of the class" );
Для проверки работоспособности этой конструкции можно использовать простой пример. Правда, при этом не следует использовать компилятор
MS VC++ 2010, так как он не поддерживает алиасов типов. Но можно воспользоваться он-лайновым компилятором GCC 4.7.1
по адресу Вот код примера
#include <type_traits>
template <typename T>
using is_bool = std::is_same<T, bool>;
template <typename T>
struct A
{
static_assert( std::is_integral<T>::value && !is_bool<T>::value,
"An integral type other than bool is required for "
"the template argument of the class" );
};
int main()
{
A<int> a1;
A<bool> a2;
return 0;
}
Здесь компилятор должен выдать сообщение об ошибке, включая текст из объявления
static_assert, при попытке инстанциировать для объекта
a2 класс
A с типом аргумента шаблона
bool.
Тем не менее этот подход имеет один недостаток. Имя
is_bool не является стандартным, а потому не принадлежит стандартному пространству имен
std::. А это может путать программистов, которые будут пытатсья поставить перед этим именем вложенное имя
std::.
Я сообщил об этом на форуме по обсуждению текущего стандарта в
isocpp, предложив данную характеристику типа
is_bool включить в стандарт языка С++.