加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 按大小存储字段的结构

发布时间:2020-12-16 09:58:17 所属栏目:百科 来源:网络整理
导读:我想知道如何在C中执行以下操作: 考虑这些类: C1 C2 C3 ...... Cn,Ci Cj表示sizeof(Ci)的sizeof(CJ) 我想要一个使用可变参数模板作为Ci序列的结构,OrderBySize AnySequenceOfCis,例如:OrderBySize C1,C2,C3,...,Cn要么 ?OrderBySize C2,C1,C4,…,CN ……
我想知道如何在C中执行以下操作:

考虑这些类:

C1< C2< C3< ......< Cn,Ci< Cj表示sizeof(Ci)<的sizeof(CJ) 我想要一个使用可变参数模板作为Ci序列的结构,OrderBySize< AnySequenceOfCis>,例如:OrderBySize< C1,C2,C3,...,Cn>要么
?OrderBySize< C2,C1,C4,…,CN> ……所有可能的组合

并给出以下结构:

class result{
  Cn elem1;
  Cn-1 elem2;
  .
  .
  .
  C1 elemn;
}

我读了this article,它显示了我们如何定义元组< typename ... T>然而,这是不同的,更难以实现并且非常有用.

编辑:

order_by_size< T1,Tn>将包含T1,Tn的有序组合的元组

但是我不希望用户知道我在命令字段,用户会像元组一样使用它.因此,为了访问字段,用户将使用:

template< typename ... Tn>
获取< size_t>(const MyStructure< Tn ...& m)获取size_t'th元素,该元素在新元组中具有另一个索引.

解决方法

基本上,这个问题简化为仅根据给定的比较器对类型列表进行排序.一旦你拥有了,其他一切都随之而来.所以这个答案只是排序部分.我们将从一个类型列表开始:

template <typename...>
struct typelist {
    using type = typelist;
};

我将假设一组非常短的元函数(头部,尾部,连续,大小).为简洁起见,我将省略它们.

所以让我们跳进编写合并排序:

template <typename TL,typename Cmp = LessSize>
struct sort
{
    using left_right = typename split<TL,size<TL>::value/2>::type;
    using left = typename sort<head_t<left_right>,Cmp>::type;
    using right = typename sort<head_t<tail_t<left_right>>,Cmp>::type;

    using type = typename merge<left,right,Cmp>::type;
};

// base case for exactly 1 element
template <typename T,typename Cmp>
struct sort<typelist<T>,Cmp> {
    using type = typelist<T>;
};

// potentially add a base case for exactly 2 elements here?

这里的一般结构看起来应该很熟悉.我们将我们的类型列表TL分成两个相等的部分,对它们进行排序,然后合并.当然,这是元编程,因此一切都不必要地复杂化.

让我们从拆分开始吧. split接受一个类型列表和一个大小,并返回两个类型列表的类型列表:第一个具有给定的大小,第二个是余数:

template <typename A,typename B,size_t N>
struct split_impl
    : std::conditional<
        size<A>::value < N,split_impl<concat_t<A,typelist<head_t<B>>>,tail_t<B>,N>,typelist<A,B>
        >::type
{ };

template <typename TL,size_t N>
struct split
    : split_impl<typelist<>,TL,N>
{ };

所以这给了我们左右(至少一次我们应用head_t<>和head_t< tail_t<>>).剩下的就是合并步骤.我正在使用Boost MPL关于元函数类的概念,所以LessSize是:

struct LessSize {
    template <typename A,typename B>
    using apply = std::integral_constant<bool,sizeof(A) < sizeof(B)>;
};

merge只需要遍历两个类型列表,并根据两个类型列表之间的比较器选择最小元素.首先,我们将从所有基本情况开始:

template <typename L,typename R,typename Cmp>
struct merge;

// R empty
template <typename... T,typename Cmp>
struct merge<typelist<T...>,typelist<>,Cmp> {
    using type = typelist<T...>;
};

// L empty
template <typename... T,typename Cmp>
struct merge<typelist<>,typelist<T...>,Cmp> {
    using type = typelist<T...>;
};

然后是递归步骤,这有点难看:

template <typename A,typename... As,typename... Bs,typename Cmp> 
struct merge<typelist<A,As...>,typelist<B,Bs...>,Cmp>
: std::conditional<
        Cmp::template apply<A,B>::value,concat_t<typelist<A>,typename merge<typelist<As...>,Cmp>::type>,concat_t<typelist<B>,typename merge<typelist<A,typelist<Bs...>,Cmp>::type>
        >::type
{ };

基本上,给定两个类型列表{A,As …}和{B,Bs …},我们选择基于Cmp的最小值,这就是我们从中弹出元素的一面.如果Cmp :: apply< A,B>,那么我们将A与{As …}与{B,Bs …}合并的结果连接起来.反之亦然.

这就是她写的全部内容:

template <typename T>
struct TD;

int main()
{
    using T = sort<typelist<int,double,char,float>,LessSize>::type;
    TD<T> r;
}

main.cpp: In function 'int main()':
main.cpp:131:11: error: aggregate 'TD<typelist<char,float,int,double> > r' has incomplete type and cannot be defined
     TD<T> r;
           ^

一旦你有了排序类型,制作一个元组很简单:

template <template <typename...> class C>
struct meta_quote {
    template <typename... T>
    using apply = C<T...>;
};

template <typename F,typename TL>
struct meta_apply;

template <typename F,typename... T>
struct meta_apply<F,typelist<T...>> {
    using type = typename F::template apply<T...>;
};

template <typename... T>
struct my_tuple
: meta_apply<meta_quote<std::tuple>,typename sort<typelist<T...>>::type
             >::type;
{ 
    using base_tuple = meta_apply<...>;
};

现在只需为get<>添加重载on my_tuple< T ...>:

template <size_t I,typename... T>
auto get(my_tuple<T...>& t) {
    using type = std::tuple_element_t<I,std::tuple<T...>>;
    return std::get<type>(static_cast<typename my_tuple<T...>::base_type&>(t));
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读