0Pricing
C++ Academy · Урок

Создание собственных признаков типов

Создавайте собственные признаки типов

«Создание собственных признаков типов» — бесплатный урок C++ Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.

Создание собственных признаков типов

Если в стандартной библиотеке нет нужного вам признака, его можно написать самостоятельно. Признак — это просто шаблон, предоставляющий ::value или ::type.

Первичный шаблон и специализация

Стандартный шаблон таков: первичный шаблон со значением по умолчанию false и специализация, соответствующая интересующему типу и устанавливающая значение true.

#include <iostream>
#include <type_traits>

template <typename T>
struct is_ptr : std::false_type {};

template <typename T>
struct is_ptr<T*> : std::true_type {};

int main() {
    std::cout << is_ptr<int>::value << "\n";
    std::cout << is_ptr<int*>::value << "\n";
    return 0;
}

Наследование от integral_constant

Унаследовав признак от std::true_type или std::false_type, вы автоматически получите член value, и признак будет вести себя как стандартные признаки типов.

Определение контейнера

Определить, похож ли тип на контейнер, можно по наличию вложенных членов. Здесь мы специализируем шаблон при наличии псевдонима типа value_type с помощью вспомогательного шаблона.

#include <iostream>
#include <vector>
#include <type_traits>

template <typename T, typename = void>
struct has_value_type : std::false_type {};

template <typename T>
struct has_value_type<T, std::void_t<typename T::value_type>> : std::true_type {};

int main() {
    std::cout << has_value_type<std::vector<int>>::value << "\n";
    std::cout << has_value_type<int>::value << "\n";
    return 0;
}

Объяснение std::void_t

std::void_t<...> преобразует любой корректный список типов в void. Если какой-либо тип внутри списка некорректен, специализация отбрасывается с помощью SFINAE, поэтому используется первичный шаблон с false_type.

Определение функции-члена

Можно определить, есть ли у типа вызываемая функция-член size(), проверив это выражение в void_t.

#include <iostream>
#include <string>
#include <type_traits>

template <typename T, typename = void>
struct has_size : std::false_type {};

template <typename T>
struct has_size<T, std::void_t<decltype(std::declval<T>().size())>> : std::true_type {};

int main() {
    std::cout << has_size<std::string>::value << "\n";
    std::cout << has_size<int>::value << "\n";
    return 0;
}

declval

std::declval<T>() создаёт фиктивное значение типа T в невычисляемом контексте, позволяя записывать выражения decltype без создания объекта.

Преобразующий признак типа

Собственные признаки типов также могут создавать типы. Этот признак удаляет один уровень указателя.

#include <iostream>
#include <type_traits>

template <typename T>
struct remove_one_pointer { using type = T; };

template <typename T>
struct remove_one_pointer<T*> { using type = T; };

int main() {
    using R = remove_one_pointer<int*>::type;
    std::cout << std::is_same_v<R, int> << "\n";
    return 0;
}

Вспомогательные шаблоны _v и _t

Следуйте стилю стандартной библиотеки, добавляя шаблоны переменных и псевдонимов.

#include <iostream>
#include <type_traits>

template <typename T>
struct is_char : std::false_type {};
template <>
struct is_char<char> : std::true_type {};

template <typename T>
inline constexpr bool is_char_v = is_char<T>::value;

int main() {
    std::cout << is_char_v<char> << "\n";
    std::cout << is_char_v<int> << "\n";
    return 0;
}

Идиома обнаружения

Техника void_t обобщается в идиому обнаружения, которую формализует экспериментальный std::is_detected. Концепции C++20 делают значительную часть этой работы проще.

Проверка собственных признаков типов

Проверяйте собственные признаки типов с помощью static_assert, чтобы любая регрессия немедленно приводила к ошибке сборки.

#include <type_traits>

template <typename T>
struct is_void_like : std::false_type {};
template <>
struct is_void_like<void> : std::true_type {};

static_assert(is_void_like<void>::value);
static_assert(!is_void_like<int>::value);

int main() { return 0; }

Быстрая проверка

Вспомните назначение std::void_t.

Итоги

Вы научились писать собственные признаки типов.

  • Первичный шаблон по умолчанию даёт false, а специализация устанавливает true
  • Наследуйтесь от true_type/false_type
  • void_t и declval лежат в основе идиомы обнаружения
  • Добавляйте вспомогательные шаблоны _v/_t и проверяйте их с помощью static_assert

Часто задаваемые вопросы

Урок «Создание собственных признаков типов» бесплатный?

Да — полный текст урока «Создание собственных признаков типов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.

Чему я научусь в уроке «Создание собственных признаков типов»?

Создавайте собственные признаки типов Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C++ Academy?

Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Создание собственных признаков типов»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C++ Academy?

Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Исследование типов
  2. Преобразование типов
  3. Условная логика
  4. Создание собственных признаков типов
← Назад к C++ Academy