Тип соответствия в списке типов с использованием шаблона C ++ - PullRequest
0 голосов
/ 18 сентября 2018

Мне нужно сопоставить тип в списке типов во время компиляции с использованием шаблона C ++. Вот мой код, но он компилируется с ошибкой. Любая идея, как я могу это исправить?

template <typename T, typename X, typename... Rs>
struct match
{
    using test = typename std::conditional<std::is_same<T, X>::value, X, bool>::type;
    using more = typename match<T, Rs...>::type;
    using type = typename std::conditional<std::is_same<test, bool>::value, more, test>::type;
};

template <typename T>
struct match<T, bool>
{
    using type = bool;
};

match<int, int, float>::type x;

Ошибка:

1.cpp:99:45: error: wrong number of template arguments (1, should be at least 2)
  using more = typename match<T, Rs...>::type;

                                         ^

1 Ответ

0 голосов
/ 18 сентября 2018

Вы должны добавить частичную специализацию для обработки случая с двумя аргументами шаблона, в противном случае создание экземпляра more приведет к созданию экземпляра match с одним аргументом шаблона, что приведет к ошибке. Ваш match<T, bool> обрабатывает только тот случай, когда последний аргумент bool, вы должны объявить его как, например,

template <typename T, typename X>
struct match<T, X>
{
    using type = typename std::conditional<std::is_same<T, X>::value, X, bool>::type;
};

Кроме того, я не знаю, в чем смысл test. Я думаю, что использование more непосредственно в определении type достаточно:

template <typename T, typename X, typename... Rs>
struct match
{
    using more = typename match<T, Rs...>::type;
    using type = typename std::conditional<std::is_same<T, X>::value, X, more>::type;
};

Это все еще не лучшее решение, потому что оно приведет к созданию экземпляра more, даже если T соответствует X (в этом случае мы можем утверждать, что match::type - это X без создания экземпляра more). Чтобы избежать ненужной реализации, вы можете добавить дополнительную частичную специализацию:

template <typename T, typename... Rs>
struct match<T, T, Rs...>
{
    using type = T;
};

При этой частичной специализации первичный шаблон соответствует только случаю, когда T не X, таким образом, вы можете еще больше упростить первичный шаблон как

template <typename T, typename X, typename... Rs>
struct match
{
    using type = typename match<T, Rs...>::type;
};

Для полноты, окончательное решение будет:

#include <type_traits>

template <typename T, typename X, typename... Rs>
struct match
{
    using type = typename match<T, Rs...>::type;
};

template <typename T, typename... Rs>
struct match<T, T, Rs...>
{
    using type = T;
};

template <typename T, typename X>
struct match<T, X>
{
    using type = typename std::conditional<std::is_same<T, X>::value, X, bool>::type;
};

static_assert(std::is_same<int, match<int, int, float>::type>::value);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...