Поиск первого непустого подтипа в аргументах шаблона - PullRequest
1 голос
/ 26 марта 2019

Я пытаюсь написать метафункцию C ++, которая возвращает мне первый непустой подтип для предоставленных параметров шаблона.

Например:

struct I { using subtype = int; };
struct D { using subtype = double; };
struct E { using subtype = empty ; };

Я пытаюсь достичь:

static_assert(std::is_same<int, first_non_empty_subtype<E,E,I>>::value, "the first non-empty subtype should be 'int'");
static_assert(std::is_same<double, first_non_empty_subtype<E,D,I>>::value, "the first non-empty subtype should be 'double'");
static_assert(std::is_same<empty, first_non_empty_subtype<E,E,E>>::value, "since all subtypes are empty, the result is empty");

Мои первые мысли об использовании std::conditional_t с рекурсией шаблона:

template <typename T, typename ...Ts>
using first_non_empty_subtype = std::conditional_t<
    !std::is_empty<typename T::subtype>::value, 
    typename T::subtype, 
    first_non_empty_subtype<Ts...>>::type

Однако я не все знаком с реализацией рекурсии шаблонов для псевдонимов типов.

Может ли кто-нибудь помочь мне указать верное направление для решения этой проблемы?

Спасибо!

1 Ответ

1 голос
/ 26 марта 2019

Я предлагаю следующее:

// ground case: no more types, so empty
template <typename ...>
struct fnes_helper
 { using type = empty; };

// the first type is T and isn't empy; so T
template <typename T, typename ... Ts>
struct fnes_helper<T, Ts...>
 { using type = T; };

// the first type is empty; so recursion
template <typename ... Ts>
struct fnes_helper<empty, Ts...> : public fnes_helper<Ts...>
 { };

template <typename ... Ts>
using first_non_empty_subtype 
   = typename fnes_helper<typename Ts::subtype...>::type;

Заметьте, что более специализированная версия fnes_helper - это версия с типом empty в первой позиции, так что в этом случае используется версия.Следует за другой специализацией, которая имеет общий тип T в первой позиции, и, наконец, у нас есть основная версия, которая выбрана в других случаях, поэтому, когда список типов пуст.

Также не забудьтедобавить {} или ::value после std::is_same в static_assert() тестах

static_assert(std::is_same<int, first_non_empty_subtype<E,E,I>>{},
              "the first non-empty subtype should be 'int'");
static_assert(std::is_same<double, first_non_empty_subtype<E,D,I>>{},
              "the first non-empty subtype should be 'double'");
static_assert(std::is_same<empty, first_non_empty_subtype<E,E,E>>{},
              "since all subtypes are empty, the result is empty");
...