Как я могу использовать класс шаблона внутри класса шаблона в качестве параметра шаблона шаблона с параметром шаблона?

Я пытаюсь использовать класс шаблона в качестве параметра шаблона шаблона с другим параметром шаблона. Как это звучит, это довольно сложно/запутанно, и я не могу понять, как исправить ошибку компилятора.

То, что я написал, похоже на «std::find_if», но работает для «std::tuple». Как показано в приведенном ниже коде, он работает, когда я указываю тип для is_same_type_tt, но когда я пытаюсь использовать параметр шаблона с is_same_type_tt, компилятор жалуется:

main.cpp:75:13: error: type/value mismatch at argument 2 in template parameter list for 'template<class TupleType, template<class> class Action> struct tuple_find_if_tt'
      >::value;
      ^

Исходный код выглядит следующим образом:

template< typename TypeLookingFor >
struct is_same_type_tt
{
    typedef TypeLookingFor type_looking_for;
    template< typename TypeCompareTo >
    struct type_tt : is_same< type_looking_for, TypeCompareTo >
    {};
};

// base for the recusion
template<
    typename TupleType
    , size_t Index
    , template< typename > class Action >
struct tuple_find_if_recur_tt;

// last in the recursion
template<
    typename TupleLast
    , size_t Index
    , template< typename > class Action >
struct tuple_find_if_recur_tt< tuple< TupleLast >, Index, Action >
    : conditional<
        Action< TupleLast >::value
        , integral_constant< size_t, Index >
        , integral_constant< size_t, -1 > >::type
{};

// recursion
template<
    typename TupleHead, typename... TupleRest
    , size_t Index
    , template< typename > class Action >
struct tuple_find_if_recur_tt<
    tuple< TupleHead, TupleRest... >, Index, Action >
    : conditional<
        Action< TupleHead >::value
        , integral_constant< size_t, Index >
        , tuple_find_if_recur_tt<
            tuple< TupleRest... >
            , Index + 1u
            , Action > >::type
{};

// wrap the recursion
template<
    typename TupleType
    , template< typename > class Action >
struct tuple_find_if_tt
    : tuple_find_if_recur_tt< TupleType, 0u, Action >
{};

В качестве теста приведенный ниже код компилируется нормально:

// this works fine.
static_assert(
    tuple_find_if_tt< tuple< int, float, double >
    , is_same_type_tt< float >::type_tt >::value == 1, "" );

Но когда я пытаюсь использовать его с еще одним параметром шаблона, он не работает:

// problem starts from here...
template< typename... Types >
struct tuple_indirect_find_tt
{
    typedef tuple< Types... > tuple_type;
    // tuple_type obj_;

    template< typename TypeLookingFor >
    static constexpr size_t find()
    {
        return tuple_find_if_tt<
            tuple_type
            // something is not right below...
            , typename is_same_type_tt< TypeLookingFor >::type_tt
            >::value;
    }
};

// this doesn't work.
static_assert(
    tuple_indirect_find_tt< int, float, double >::find< float >()
    == 1, "" );

Чтобы заставить его работать, мне пришлось реорганизовать классы шаблонов, чтобы я мог сделать следующее:

return tuple_find_if_tt<
    tuple_type
    , is_same_type_tt
    , typename TypeLookingFor // this is separated from is_same_type_tt
    >::value;

Обходной путь не кажется таким уж плохим, но мне все же хотелось бы знать, что я сделал не так. Если это не возможный подход, я хотел бы знать, какой стандарт С++ предотвращает это.

Спасибо за чтение.


person Jae Hyuk Kwak    schedule 03.11.2015    source источник


Ответы (1)


typename is_same_type_tt< TypeLookingFor >::type_tt

type_tt не является типом. Выше вы утверждаете, что это так. Ваша ложь сбивает с толку компилятор, заставляя его думать, что это не соответствует параметру template<class>class.

Попробуйте is_same_type_tt< TypeLookingFor >::template type_tt.

Здесь мы говорим, что зависимое имя type_tt является template, а не typename.

person Yakk - Adam Nevraumont    schedule 03.11.2015
comment
Спасибо! Кажется, это работает. Но для лучшего обсуждения я поставил typename для is_same_type_tt‹ TypeLookingFor ›. Насколько я знаю, когда параметр шаблона используется в классе шаблона, перед ним должно стоять имя типа. Например, vector‹ float › подходит всегда, но vector‹ Type ›, где Type исходит из параметра шаблона, должен иметь typename. Кажется, я пробовал typename is_same_type_tt‹ TypeLookingFor ›::template type_tt, но это не сработало. Я не уверен, почему в этом случае у меня не должно быть ключевого слова typename. - person Jae Hyuk Kwak; 04.11.2015
comment
@JaeHyukKwak нет; typename требуется только для зависимых типов. Экземпляр шаблона is_same_type_tt должен создавать тип, поэтому is_same_type_tt< blah > является типом. Зависимый тип ::something может быть значением (токен перечисления, статический и т. д.), типом или шаблоном. Использование typename говорит о том, что это тип. - person Yakk - Adam Nevraumont; 04.11.2015