Dyzzet|
C++ Data Science Алгоритмы Темы · Блог · YouTube
Как ограничить значения шаблонного параметра
От C++03 к C++11, 14 и 20

Представим, что есть класс, например, произвольного числа с плавающей запятой: с помощью шаблона пользователь может задать любые размеры экспоненты и мантиссы (size_t E, size_t M).

template <size_t E, size_t M>
class CustomFloat
{
    // ...
};

Как ограничить пользователя и задать: \(E\geqslant 5\) и \(M\geqslant 10\)? То есть значения \(E=8,\) \(M=23\) подходят:

CustomFloat<8, 23> f{};

А, например, значения \(E=4,\) \(M=10\) должны приводить к ошибке компиляции.

C++11

Если первый параметр шаблона true, то используется специализация с полем того же типа, что и второй параметр (см. ниже реализацию); my_enable_if_t<...> заменяется на тип, отличный от void. Если первый параметр шаблона false, используется неспециализированный шаблон пустой структуры, а второй параметр считается типом void; my_enable_if_t<...> заменяется на void, что не может быть скомпилировано.

Стандарт C++11 для таких целей ввёл шаблонную структуру std::enable_if.

template <size_t E, size_t M, std::enable_if<(E >= 5 && M >= 10), size_t>::type = 0>
class CustomFloat
{
    // ...
};

C++14

Стандарт C++14 ввёл псевдоним std::enable_if_t, чтобы не приходилось писать ::type.

template <size_t E, size_t M, std::enable_if_t<(E >= 5 && M >= 10), size_t> = 0>
class CustomFloat
{
    // ...
};

C++03

Пойдём немного вразрез с хронологией и посмотрим, как такое можно было проделать раньше; например, реализовать свой std::enable_if — my_enable_if и псевдоним члена type — my_enable_if_t.

template <bool B, typename T = void>
struct my_enable_if
{};
 
template <typename T>
struct my_enable_if<true, T>
{
    typedef T type;
};
 
template <bool B, typename T = void>
using my_enable_if_t = typename my_enable_if<B, T>::type;
template <size_t E, size_t M, my_enable_if_t<(E >= 5 && M >= 10), size_t> = 0>
class CustomFloat
{
    // ...
};

C++20: концепты

Концепты — возможность, которую специально ввели, чтобы решать эту проблему.

template <size_t E, size_t M>
requires (E >=5 && M >= 10)
class CustomFloat
{
    // ...
};

Можно оформить концепт в виде самостоятельной сущности, чтобы использовать многократно.

template <size_t E, size_t M>
concept MinExponentAndMantissa = (E >= 5 && M >= 10);
 
template <size_t E, size_t M>
requires MinExponentAndMantissa<E, M>
class CustomFloat
{
    // ...
};

Приложение: исходный код.

20 августа 2022
Зарегистрируйтесь и войдите, чтобы оставлять комментарии и голосовать.

Также может быть интересным
© MMXI—MMXXIII. RSS. Поддержать сайт
Светлая тема / тёмная тема