Как я могу получить доступ к этому вложенному параметру шаблона? - PullRequest
0 голосов
/ 26 июня 2018

Вот мой код:

template<
    template <typename TSEvent,
              typename ...TSEvents> typename V,
    typename... Filtered>
constexpr auto filter() {
    if constexpr(sizeof...(TSEvents) == 0) {
        return type_list<Filtered...>{};
    }
    if constexpr(is_default_constructible<TSEvent>::value) {
        return filter<<TSEvents...>, Filtered...>();
    }
    return filter<<TSEvents...>, Filtered...>();
}

Однако я получаю эту ошибку, size...(TSEvents), TSEvents не объявлено. Можно ли в любом случае получить доступ к TSEvents в моем вложенном шаблоне?

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

Однако я получаю эту ошибку, размер ... (TSEvents), TSEvents не объявлен. Могу ли я получить доступ к TSEvents в моем вложенном шаблоне?

Краткий ответ: нет.

Длинный ответ: с

template<
    template <typename TSEvent,
              typename ...TSEvents> typename V,
    typename... Filtered>
constexpr auto filter()

вы задали два аргумента шаблона для функции filter().

Первый, относящийся к списку переменных TSEvents, является аргументом шаблона-шаблона, который получает аргумент одного или нескольких типов.

Но ваша функция не получает тип , основанный на этом шаблоне-шаблоне (с фиксированным типом TSEvent и фиксированным TSEvents); получить шаблон-шаблон.

Так что не имеет смысла тест size...(TSEvents), потому что для filter() это не так исправлен список TSEvents.

Чтобы объяснить это по-другому ... вы можете вызвать фильтр таким образом

filter<std::tuple, short, int, long>();

Запрашивает sizeof...(TSEvents) спрашивает, сколько типов содержит std::tuple, где std::tuple является только контейнером типов, но без содержащихся типов.

Если вы хотите выполнить какие-либо действия в функции filter(), вам нужен параметр шаблона type , а не параметр template-template.

Проще с классами (см. Ответ AndyG), где вы можете использовать частичную специализацию (с функциями, которые вы не можете) или с функцией, когда они получают аргументы, из которых вы можете выводить типы.

Предположим, что ваш filter() получил объект типа V<SomeTypes...> и объект типа std::tuple<Filtered...>, вы можете написать что-то следующим образом (осторожно: код не проверен)

template<
    template <typename ...> typename V,
    typename TSEvent, typename ... TSEvents, typename... Filtered>
constexpr auto filter (V<TSEvent, TSEvents...> const & v,
                       std::tuple<Filtered...> const & t) {
   /* some code where you can use also TSEvent and TSEvents... */
}

Таким образом TSEvent и TSEvents... выводятся из аргумента v.

0 голосов
/ 27 июня 2018

Просто, чтобы представить другой вариант, вы можете сделать это только с функциями.

#include <iostream>
using namespace std;
template<typename...>
struct type_list{};

template < template <typename...> typename T,typename A,typename... B, typename... Filtered> 
constexpr auto filter_impl(T<A,B...>*,type_list<Filtered...>)
{

    using filtered_list = std::conditional_t<is_arithmetic<A>::value,
                        type_list<Filtered...,A>,
                        type_list<Filtered...>>;

    if constexpr (sizeof...(B) == 0)
        return filtered_list();
    else
        return filter_impl( (T<B...>*)0, filtered_list());
}

template <typename T> 
constexpr auto filter()
{
    return filter_impl( (T*)0,type_list<>());
}

struct not_arethmetic{};



int main() {
    auto b = filter< type_list<not_arethmetic,int,bool,not_arethmetic,double> >();
    static_assert(std::is_same< decltype(b) , type_list<int,bool,double>>::value);
    return 0;
}

Демо

Одна вещь, в вашем исходном примере ваше первое выражение if будет означать, что окончательное TSEvent не проверяется, так как оно возвращает, если varadic TSEvents ... имеет нулевой размер, но будет один последний элемент для проверки, является ли is_default_constructible.

Также, вы можете найти этот пост полезным в отношении имен параметров шаблона шаблона.

0 голосов
/ 26 июня 2018

Обычно через другой уровень косвенности, и обычно struct, который мы можем специализировать.

Например:

namespace detail
{
    template<class...>
    struct filter_t;

    template<template<class, class...> class V, class TSEvent, class... TSEvents, class... Filtered>
    struct filter_t<V<TSEvent,TSEvents...>, Filtered...>
    {
        static constexpr auto filter() {
            return sizeof...(TSEvents);
         }
    };
} // detail

template<class... T>
constexpr auto filter()
{
    return detail::filter_t<T...>::filter();
}

template<class T, class...U>
struct type_list{};

int main()
{
    std::cout << filter<type_list<int, int, int>, int>();
}

Live Demo

...