标签:c c11 templates struct variadic-templates
我想知道如何在C中执行以下操作:
考虑这些类:
C1< C2< C3< ......< Cn,Ci< Cj表示sizeof(Ci)<的sizeof(CJ)
我想要一个使用可变参数模板作为Ci序列的结构,
OrderBySize< AnySequenceOfCis>,例如:OrderBySize< C1,C2,C3,...,Cn>要么
OrderBySize< C2,C1,C3,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 B, 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...>, typelist<B, Bs...>, Cmp>::type>,
concat_t<typelist<B>, typename merge<typelist<A, As...>, 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));
}
标签:c,c11,templates,struct,variadic-templates 来源: https://codeday.me/bug/20190727/1558382.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。