微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 使用gnu 11和没有stdlib(Arduino环境)在编译时过滤值列表

我正在研究一个Arduino项目,这意味着C方言目前是C 11的gnu 11超集,并且stdlib不可用(没有元组,没有数组,没有任何东西;命名空间std只是空的!).

出于优化原因(cpu有16K的FLASH,2K的RAM和这个特殊的低电压版本运行在8MHz)我希望编译器尽可能地预先计算以提供运行时代码,尤其是中断服务程序,“友好的“数据.

现在我想做的是以下内容

给定一个(唯一的)整数列表,我想提取与任意过滤器匹配的值.
然后我想构建一个索引表,允许通过它们的初始索引到达过滤后的元素

例如2,10,4,7,9,3,滤波器值<1. 8可以产生过滤列表2,3和索引表0,-1,1,2,3.
只要索引表保持一致,过滤后的数组中元素的顺序就无关紧要了.

我坚持认为我需要不断的数组.动态生成这些数据非常简单,但我希望编译器能够完成这项工作,而无需在运行时执行单个指令.

初始列表将由普通的#define给出,结果将是常量数组,例如:

#define my_list 2,3

constexpr bool filter (int value) { return value < 8; }

const int    filtered_list [] = filter_list <filter>(my_list);
const size_t filtered_index[] = filter_index<filter>(my_list);

问题是,如果可行的话,如何使用准系统C 11和没有stdlib实现这些filter_list和filter_index模板?

我对错误处理不感兴趣,已经处理了空列表或重复值等异常情况.我宁愿看到最简单的可能实现,即使对数据有效性做出了一些假设.

模板,过滤器或初始列表的确切形式也无关紧要.重要的是从唯一的列表定义中获取数组.
例如,我不介意一种语法,其中列表的每个元素都是单独声明的(虽然我无法想象它是如何工作的).

我更喜欢拥有一个独立的C源代码.另一方面,如果Python可以在几十行中实现,需要隐藏模板的页面,包括重写std :: array和std :: tuple,我宁愿写一些外部预处理器.

解决方法

有一种方法可以避免大多数样板使用函数模板而不是完整类.最后一个类模板是必需的,因为对于c中的函数没有返回类型推导.使用int而不是typename T来跳过不重要的模板参数.当atmel将其工具链更新为gcc5或更新时,c 14支持可以进一步缩小代码.
#define LIST  2,3
constexpr bool less8(int v) { return v < 8; }

typedef bool(*predicate)(int);

template<int... values>
struct seq {};

template<int N>
struct array {
      const int   data[N];
};

template<int... values>
constexpr array<sizeof...(values)> to_array(seq<values...>) { return {{ values... }}; }

template<typename trueType,typename falseType>
constexpr falseType select(seq<0>,trueType,falseType) { return {}; }

template<typename trueType,typename falseType>
constexpr trueType select(seq<1>,falseType) { return {}; }

template<int... first,int... second>
constexpr seq<first...,second...> append(seq<first...>,seq<second...>) { return {}; }

template<predicate p,typename N,typename V>
struct filter_impl;

template<predicate p,int next>
struct filter_impl<p,seq<next>,seq<>> {
      using type = seq<>;
};

template<predicate p,int next,int first,int... rest>
struct filter_impl<p,seq<first,rest...>> {
      using type = decltype(
            append(
                  select(seq<p(first)>{},seq<next>{},seq<-1>{}),typename filter_impl<p,decltype(select(seq<p(first)>{},seq<next+1>{},seq<next>{})),seq<rest...>>::type{}
            )
      );
};

extern constexpr auto  const_indices = to_array(filter_impl<less8,seq<0>,seq<LIST>>::type{});

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐