hw-tp-05-has-value-type-Z3tAa

0
Readme.md

1. Задача: Проверка Наличия Вложенного Типа (HasValueType)

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

T
является контейнером и имеет вложенный
value_type
?

Это задание — спроектировать и реализовать один из ключевых архитектурных компонентов метапрограммирования: "type trait" (характеристику типа) для проверки наличия вложенного типа на этапе компиляции.

Задача: Написать шаблонную метафункцию (в виде struct), которая определяет, содержит ли заданный тип T вложенный тип с именем value_type.

Техническое Задание (ТЗ)

1. Основной интерфейс (C++):

Метафункция должна предоставлять

::value
(как
bool
константа) или наследоваться от
std::true_type
/
std::false_type
.

2. Ключевые требования к метафункции:

  • Работа на этапе компиляции: Вся логика должна выполняться компилятором.
  • Корректность SFINAE: Метафункция не должна приводить к ошибке компиляции, если
    value_type
    отсутствует. Она должна просто возвращать
    false
    .
  • Наследование: Для удобства использования, метафункция должна наследоваться от
    std::true_type
    или
    std::false_type
    .

3. Сетевой интерфейс (REST API):

  • Неприменимо. Это компонент для использования на этапе компиляции.

Архитектура и алгоритм

Для реализации этой проверки используется техника SFINAE (Substitution Failure Is Not An Error) в сочетании с

std::void_t
(C++17).

  1. Базовый шаблон: Создается базовый шаблон (например,
    HasValueType_Impl
    ), который по умолчанию наследуется от
    std::false_type
    .
  2. Частичная специализация: Создается частичная специализация этого шаблона. Эта специализация использует
    std::void_t<typename T::value_type>
    в качестве одного из шаблонных параметров.
  3. Механизм выбора:
    • Если
      T::value_type
      существует, выражение
      std::void_t<typename T::value_type>
      корректно "вычисляется" (в тип
      void
      ), и компилятор выбирает эту более специализированную версию, которая наследуется от
      std::true_type
      .
    • Если
      T::value_type
      не существует, подстановка (substitution) в специализации проваливается. Благодаря SFINAE, это не ошибка — компилятор просто игнорирует эту специализацию и возвращается к базовому шаблону, который наследуется от
      std::false_type
      .

Пример интерфейса (C++)

Этапы выполнения

  1. Создайте базовый шаблон
    HasValueType
    , наследуемый от
    std::false_type
    .
  2. Реализуйте частичную специализацию, использующую
    std::void_t
    для проверки
    typename T::value_type
    .
  3. Напишите тесты (например, с
    static_assert
    или
    gtest
    ), которые проверяют:
    • HasValueType_v<std::vector<int>>
      (должно быть
      true
      ).
    • HasValueType_v<int>
      (должно быть
      false
      ).

Дополнительное Задание (для заинтересованных)

Реализовать проверку на наличие функции-члена

begin()

Проблема: Проверять наличие типов (

::value_type
) проще, чем наличие функций-членов (
.begin()
). Задача: Реализовать метафункцию
HasBegin<T>
, которая проверяет, можно ли у экземпляра типа
T
вызвать функцию-член
begin()
. Сложность: Требует использования
decltype
и проверки корректности выражения
std::declval<T&>().begin()
.