Имеет элемент шаблона — вычет шаблона шаблона

Скажем, у меня есть два следующих тест-класса:

struct TestYes {
using type = void;
template <typename... T>
using test = void;
};

struct TestNo { };

и я хочу определить, есть ли у них этот элемент шаблона test,

Для участника type,

template <typename, typename = void>
struct has_type_impl {
using type = std::false_type;
};
template <typename T>
struct has_type_impl<T, typename T::type> {
using type = std::true_type;
};
template <typename T>
using has_type = typename has_type_impl<T>::type;

работает отлично:

static_assert( has_type<TestYes>::value, ""); // OK
static_assert(!has_type<TestNo>::value, "");  // OK

но эквивалент для члена шаблона test:

template <typename, template <typename...> class = std::tuple>
struct has_test_impl {
using type = std::false_type;
};
template <typename T>
struct has_test_impl<T, T::template test> {
using type = std::true_type;
};
template <typename T>
using has_test = typename has_test_impl<T>::type;

терпит неудачу на

static_assert( has_test<TestYes>::value, "");

Я знаю, что могу использовать SFINAE как:

template <typename T>
struct has_test_impl {
private:
using yes = std::true_type;
using no = std::false_type;

template <typename U, typename... Args>
static auto foo(int) -> decltype(std::declval<typename U::template test<Args...>>(), yes());

template <typename> static no foo(...);

public:
using type = decltype(foo<T>(0));
};

template <typename T>
using has_test = typename has_test_impl<T>::type;

но мне интересно, почему компилятор правильно вычитает частичную специализацию has_type_impl в то время как это остается на первом определении has_test_impl,

Заранее спасибо за ваше просвещение!

3

Решение

template<template<class...> class...>
using void_templ = void;

template <typename, typename = void>
struct has_test_impl {
using type = std::false_type;
};
template <typename T>
struct has_test_impl<T, void_templ<T::template test>> {
using type = std::true_type;
};
2

Другие решения


По вопросам рекламы [email protected]