Вы должны добавить частичную специализацию для обработки случая с двумя аргументами шаблона, в противном случае создание экземпляра 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);