шаблон псевдонима не является шаблоном класса?

Я пытаюсь написать черту типа, чтобы определить, есть ли у типа T::type определенного типа. Я использую код из этого ответа. Для справки это часть кода, который я использую:

// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf.
template <typename...>
using void_t = void;

// Primary template handles all types not supporting the operation.
template <typename, template <typename> class, typename = void_t<>>
struct detect : std::false_type {};

// Specialization recognizes/validates only types supporting the archetype.
template <typename T, template <typename> class Op>
struct detect<T, Op, void_t<Op<T>>> : std::true_type {};

Я начал с простого, обнаружив T::type:

template <typename T>
using has_type_t = typename T::type;

template <typename T>
using has_type = detect<T, has_type_t>;

Это работает так, как ожидалось, но когда я запрашиваю фактический тип T::type, я также получаю ошибки, которых я не понимаю:

template <typename X>
struct has_X_type_helper {
    template <typename T>
    using type = typename std::enable_if_t<std::is_same_v< typename T::type, X>,int>;
};

template <typename T,typename X>
using has_X_type = detect<T,has_X_type_helper<X>::type>;

GCC:

<source>:49:55: error: type/value mismatch at argument 2 in template parameter list for 'template<class, template<class> class<template-parameter-1-2>, class> struct detect'
   49 | using has_X_type = detect<T,has_X_type_helper<X>::type>;
      |                                                       ^
<source>:49:55: note:   expected a class template, got 'has_X_type_helper<X>::type'

и Clang меня еще больше сбивает с толку

<source>:49:29: error: template argument for template template parameter must be a class template or type alias template
using has_X_type = detect<T,has_X_type_helper<X>::type>;
                            ^

has_X_type_helper<X>::type - это не шаблон псевдонима типа? Что не так в моем коде?

@ godbolt


person 463035818_is_not_a_number    schedule 09.06.2020    source источник


Ответы (1)


Вам нужно указать, что вложенная вещь является шаблоном:

template <typename T, typename X>
using has_X_type = detect<T, has_X_type_helper<X>::template type>;
//                                               ~~~~~~~~~^
person Piotr Skotnicki    schedule 09.06.2020
comment
я думаю, что это новая вершина в моем списке наиболее необычного синтаксиса. Это нужно, потому что has_X_type_helper - это шаблон? или потому что has_X_type_helper<X>::type это шаблон? Я все еще нахожу это немного запутанным, потому что has_X_type_helper<X> - это просто тип, а has_X_type_helper<X>::type - шаблон, так же как has_type_t - один - person 463035818_is_not_a_number; 09.06.2020
comment
ах, я думаю, я понял. has_X_type_helper может иметь специализации, поэтому мне нужно заверить компилятор, что type является шаблоном - person 463035818_is_not_a_number; 09.06.2020
comment
@ idclev463035818 Да, та же история, что и с typename. В противном случае компилятор предполагает, что это значение типа std::is_const<T>::value, поэтому он сообщает 'type/value mismatch' - person Piotr Skotnicki; 09.06.2020