简体   繁体   English

C ++ typelist make子列表

[英]C++ typelist make sublist

Let's says I have a type 我们说我有一个类型

template<typename ...Ts>
struct typelist {};

I need to get a sublist from this list : 我需要从这个列表中获取一个子列表:

template<int startInclusive, int stopExclusive, typename ...Ts>
struct sublist {
    using type = ?; //
};

for example 例如

sublist<1, 3, int, float, double, char>::type == typelist<float, double>

When start = 0 I have a working tail implementation : start = 0我有一个工作尾部实现:

template<typename ...Ts>
struct typelist {};

template<int N, typename T, typename ...Ts>
struct tail {
    using type = typename tail<N - 1, Ts...>::type;
};

template<typename T, typename ...Ts>
struct tail<0, T, Ts...> {
    using type = typelist<T, Ts...>;
};

using T = tail<1, int, double>::type;

#include <typeinfo>
#include <cstdio>

int main() {
   ::printf("%s\n", typeid(T).name());
}

However, I cannot get anything working for start > 0 但是,我无法为start > 0

As usual, std::index_sequence helps here: 像往常一样, std::index_sequence在这里有帮助:

template <std::size_t Offset, typename Seq, typename Tuple> struct sublist_impl;

template <std::size_t Offset, std::size_t ... Is, typename Tuple>
struct sublist_impl<Offset, std::index_sequence<Is...>, Tuple>
{
    using type = std::tuple<std::tuple_element_t<Offset + Is, Tuple>...>;
};

template<std::size_t startInclusive, std::size_t stopExclusive, typename ...Ts>
using sublist = typename sublist_impl<startInclusive,
                                 std::make_index_sequence<stopExclusive - startInclusive>,
                                 std::tuple<Ts...>>::type;

Demo 演示

It's likely to be an overkill, but it works: 它可能是一种矫枉过正,但它有效:

template<typename... Ts>
struct typelist {};

template<class Typelist, typename T>
struct prepend;

template<typename... Ts, typename T>
struct prepend<typelist<Ts...>, T> {
    using type = typelist<T, Ts...>;
};

template<int start, int stop, int i, typename... Ts>
struct sublist_impl {
    using type = typelist<>;
};

template<int start, int stop, int i, typename T, typename... Ts>
struct sublist_impl<start, stop, i, T, Ts...>
{
private:
    static constexpr auto get_sublist_type() {
        if constexpr (i < start)
            return typename sublist_impl<start, stop, i + 1, Ts...>::type{};
        else if constexpr (i < stop)        
            return typename prepend<typename sublist_impl<
                start, stop, i + 1, Ts...>::type, T>::type{};
        else
            return typelist<>{};
    }

public:
    using type = decltype(get_sublist_type());
};

template<int start, int stop, typename... Ts>
struct sublist {
    using type = typename sublist_impl<start, stop, 0, Ts...>::type;
};

template<int start, int stop, typename... Ts>
using sublist_t = typename sublist<start, stop, Ts...>::type;

static_assert(std::is_same_v<
    sublist_t<1, 3, int, float, double, char>, typelist<float, double>>);

static_assert(std::is_same_v<
    sublist_t<0, 0, int, float, double, char>, typelist<>>);

static_assert(std::is_same_v<
    sublist_t<4, 4, int, float, double, char>, typelist<>>);

static_assert(std::is_same_v<
    sublist_t<0, 3, int, float, double, char>, typelist<int, float, double>>);

static_assert(std::is_same_v<
    sublist_t<0, 4, int, float, double, char>, typelist<int, float, double, char>>);

Just for fun, the std::tuple_cat() way 只是为了好玩, std::tuple_cat()方式

#include <tuple>
#include <type_traits>

template<typename ...Ts>
struct typelist
 { };

template <std::size_t sI, std::size_t sE, std::size_t I, typename T>
constexpr std::enable_if_t<(I >= sI) && (I < sE),
                           std::tuple<typelist<T>>> getTpl ();

template <std::size_t sI, std::size_t sE, std::size_t I, typename T>
constexpr std::enable_if_t<(I < sI) || (I >= sE),
                           std::tuple<>> getTpl ();

template <typename ... Ts>
constexpr typelist<Ts...> getList (std::tuple<typelist<Ts>...>);

template <std::size_t sI, std::size_t sE, typename ... Ts,
          std::size_t ... Is>
constexpr auto getTplList (typelist<Ts...>, std::index_sequence<Is...>)
   -> decltype( getList(std::tuple_cat(getTpl<sI, sE, Is, Ts>()...)) );

template <std::size_t startI, std::size_t stopE, typename ... Ts>
struct sublist
 {
   using type = decltype(getTplList<startI, stopE>
                         (typelist<Ts...>{},
                          std::index_sequence_for<Ts...>{}));
 };

int main ()
 {
   using type1 = typename sublist<1u, 3u, int, float, double, char>::type;
   using type2 = typelist<float, double>;

   static_assert( std::is_same<type1, type2>::value, "!" );
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM