簡體   English   中英

從類型列表到參數包

[英]From typelist to argument pack

我有一個這里描述的表單的類型列表:

http://www.drdobbs.com/generic-programmingtypelists-and-applic/184403813

每種類型都有一個名為get()的鴨子類型函數(模板/編譯時虛擬get() ,它返回一個簡單的類型,如下所示:

struct Float {
  float get() { return 7.0; }
};
struct Int {
  int get() { return 7; }
};
typedef typelist<Float, typelist<Int, null_typelist>> types;

我還有一個函數,它采用可變數量的簡單類型參數,如下所示:

template<typename... Args>
foo(Args... args)
{
}

現在我需要一種方法來調用foo給定的types 我認為有一個解決方案,通過元組,但我真的離一個有效的解決方案很遠......我希望你能在這里幫助我!

此代碼將typelist轉換為tuple並使用簡單類型調用foo

#include <tuple>
#include <iostream>

template<typename H, typename T>
struct typelist
{
    typedef H Head;
    typedef T Tail;
};

struct null_typelist {};


template<int... Indices>
struct indices {
    using next = indices<Indices..., sizeof...(Indices)>;
};

template<int Size>
struct build_indices {
    using type = typename build_indices<Size - 1>::type::next;
};

template<>
struct build_indices<0> {
    using type = indices<>;
};

template<typename T>
using Bare = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

template<typename Tuple>
constexpr
typename build_indices<std::tuple_size<Bare<Tuple>>::value>::type
make_indices()
{ return {}; }

template<typename T, typename... Args>
struct tuple_push;

template<typename T, typename... Args>
struct tuple_push<T, std::tuple<Args...>>
{
    typedef std::tuple<Args..., T> type;
};

template<typename TL>
struct typelist_to_tuple;

template<typename H, typename T>
struct typelist_to_tuple<typelist<H, T>>
{
    typedef typename tuple_push<H, typename typelist_to_tuple<T>::type>::type type;
};

template<typename H>
struct typelist_to_tuple<typelist<H, null_typelist>>
{
    typedef std::tuple<H> type;
};

struct Float {
  float get() const { return 7.5; }
};
struct Int {
  int get() const { return 7; }
};

template<typename... Args>
void foo(const Args&... args)
{
}

template<typename T, typename... Args>
void foo(const T& current, const Args&... args)
{
    std::cout << current << std::endl;
    foo(args...);
}

template<typename Tuple, int... Indices>
void apply(const Tuple& tuple, indices<Indices...>)
{
    foo(std::get<Indices>(tuple).get()...);
}

template<typename Tuple>
void apply(const Tuple& tuple)
{
    apply(tuple, make_indices<Tuple>());
}

int main()
{
    typedef typelist<Int, typelist<Float, typelist<Int, null_typelist>>> list;
    typedef typelist_to_tuple<list>::type tuple;
    tuple t = std::make_tuple(Int(), Float(), Int());
    apply(t);
}

現場例子

我認為這可以在不使用std::tuple情況下完成。 正如其他人所提到的,C++11 及更高版本支持基於參數包的類型列表,這比 C++03 遞歸類型列表更容易使用:

template <typename...>
struct tlist {};

假設 C++03 類型列表是您無法更改的 API 的一部分,那么第一件事就是將 C++03 類型列表轉換為 C++11 類型列表。 這可以通過一些充當類型函數的空函數聲明來完成:

// Concatenate two tlist types
template <typename... Ts, typename... Us>
static auto concat_impl(tlist<Ts...>, tlist<Us...>) -> tlist<Ts..., Us...>;

// Base case
static auto to_tlist_impl(null_typelist) -> tlist<>;

// Recursive case
template <typename Head, typename Tail>
static auto to_tlist_impl(typelist<Head, Tail>)
    -> decltype(concat_impl(tlist<Head>{}, to_tlist_impl(Tail{})));

// Alias template to make usage easier
template <typename Typelist>
using to_tlist = decltype(to_tlist_impl(Typelist{}));

接下來,提供一個輔助函數以從tlist取出參數包並將其傳遞給foo函數。 最初的問題沒有指定應該如何構造類型,所以這里它們只是在傳遞給foo默認構造。

template <typename... Ts>
void call_foo(tlist<Ts...>) {
    foo(Ts{}...);
}

最后,要使用遞歸typelist類型調用foo ,只需使用to_tlist類型函數將其轉換為tlist

    using list = typelist<Int, typelist<Float, typelist<String, null_typelist>>>;
    call_foo(to_tlist<list>{});

Godbolt 示例: https ://godbolt.org/z/j8P55v7Kb

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM