所有由qicosmos发布的文章

编译期遍历std::array

需求

在编译期遍历一个std::array,并且保证遍历的索引为编译期常量。

实现代码:

如何实现函数参数过滤代码点评

前面提出了一个参数过滤的需求,社区的一些朋友给出了实现,在这里做一下点评。

需求

过滤传入的函数参数。假设传入了int, bool, double, bool, structA这几个参数,现在我需要把其中的bool参数去掉,只保留非bool的参数,因此输入的参数经过过滤之后就变成一个tuple<int, double, structA>了。

实现思路:

实现方法有两种(当然,也许还有更多的方法)。

第一种思路

展开变参的过程中忽略特定类型,其它类型的参数重新组成一个tuple,这种方法比较直接了当。社区的Jaly就是这样做的,下面是他的实现代码:

这个代码的实现简洁又灵活,代码很少,并且能支持任意类型的过滤,非常精彩。

除了上面的实现之外,还有一种实现方法,利用c++17的fold expression去过滤,这也是我的实现方法。具体代码如下:

这个实现相比Jaly的实现,代码更多,还不够灵活,不能对任意类型进行过滤。虽然用到了C++17的fold expression,但是没有Jaly的实现那么简洁灵活,而且还用到了运算符重载,存在运算符重载冲突的可能性。算是展示fold expression的一种用法吧。

社区的yiShuiHanFeng实现了过滤bool参数并调用过滤bool后的目标函数,下面是他的实现:

yiShuiHanFeng是通过函数递归调用来过滤bool的,但是他在过滤bool的同时又把需要的参数保留,通过不断把非bool的参数往后放来实现的,最终实现目标函数调用,中间不会生成中间变量,实现得非常精妙,很赞!

第二种思路

在编译期得到过滤之后的参数索引。展开参数类型,排除bool类型,并把非bool类型的参数索引保存到index_sequence,后面根据这个index_sequence就可以得到过滤后的参数。下面是fesil的实现:

这个实现也很棒,也能对任意类型进行过滤,实现用到了c++17的if constexpr,让代码变得更简单了,虽然相比第一种实现方法稍显复杂一点,但仍然是一个不错的思路。

总结

这个需求大家积极参与并且给出了精彩的实现,非常好。可以看到同一个需求却有着不同的实现思路和实现方法,体现了元编程灵活与精巧。

本次实现得最好的是Jaly,他的代码最短又灵活,其次是fesil,yiShuiHanFeng的参数移动也很精妙。

cinatra发布新版本

cinatra发布v0.04版本

这仍然是一个预发布版本,增加了一些有用的功能和改进了接口的易用性,欢迎大家试用!

modern c++做web开发给你飞一般的感觉!

最近改进的几个地方

cinatra本次改进增加了http缓存和更友好的html渲染接口:

示例

1.http缓存

这样就可以实现缓存了,这里设置的是全局缓存,即所有的http get请求都会缓存。

如果希望某些请求不缓存该怎么做呢?设置一个enable_cache参数即可:

这样就可以实现某个请求不缓存,除此之外的缓存。

2. 更友好的html渲染接口

如何实现函数参数过滤

需求

过滤传入的函数参数。假设传入了int, bool, double, bool, structA这几个参数,现在我需要把其中的bool参数去掉,只保留非bool的参数,因此输入的参数经过过滤之后就变成int, double, structA了。

如何实现这个需求,请大家把实现的代码发在文后,看看谁实现得最好,期待精妙的代码。

注意

评论的时候展示代码的话需要用一个代码格式,否则显示不正常,要类似于这样在代码外面套一个脚本:

pre class=”lang:c++ decode:true “

cinatra最新的改进

最近改进的几个地方

cinatra本次改进主要侧重于易用性和灵活性,主要增加了下面几项功能:

  1. response时自动添加对应的mime type
  2. 支持中文
  3. 内置小的静态资源获取
  4. 支持pathinfo/*

示例

1.response时设置mime type

2.中文

3.pathinfo

4.静态资源获取

purecpp社区寻求赞助和捐赠

purecpp社区的朋友们:

非常感谢大家对purecpp社区的热爱和支持,你们的支持对于purecpp社区很重要,对于modern c++很重要。

近来频繁出现了社区网站挂掉的情况,主要原因是在云主机有限的配置下资源占用过大导致的。由于社区现在是基于wordpress(php)改造的,所以性能和并发量非常有限,因此我计划将社区网站从php更换为c++的feather,feather的性能是php的数十倍,相信社区更换为feather之后,在相同资源的情况下,能够在很长一段时间内满足使用需求。

除了更换社区框架之外还需要对云主机进行升级,需要购买新的云主机,因此需要大家赞助或捐赠,金额不限,只要能维持社区网站的正常运行即可。捐赠者名单和金额也将在社区定期公布,当然如果你不希望公布自己的捐赠信息可以在捐赠的时候注明一下。

捐赠方式:微信和支付宝
微信:
weixin

支付宝:
zfb

Feather–一个快速开发的web服务器框架

Feather是一个适合快速开发的modern c++ web框架,Feather的目标是让使用者以最小的精力和成本来开发一个web网站。

现在很多web框架都非常庞大,学习成本高,而Feather正是为了解决这些问题的,它就像它的名字feather那样轻盈,所有的一切都是为了让用户非常方便又快速地开发而不是陷入到框架的细节当中。

一个好的框架应该是能让用户轻松实现自己的想法而不是成为框架的奴隶。如果你希望轻松快速地开发一个web网站,而无需花费大量的精力去学习框架细节的话,那么Feather非常适合你!

Feather是什么?

Feather作为一个快速开发框架,它的目标是让web开发变得简单。它主要有下面几个特点:

  1. 简洁易用
  2. 高性能,modern c++(c++17)开发
  3. header only
  4. 跨平台
  5. 支持编译期反射
  6. 支持AOP

Feather框架的核心包括:
1. 一个易用的http库,支持http1.x, https, websocket
2. 一个功能强大的html模版引擎
3. 一个可扩展的ORM库,支持多种数据库(mysql,postgresql,sqlite)
4. 一个可扩展序列化库,支持多种格式(json, xml)

Feather的架构

下面是Feather的架构图:

Feather的架构图

Feather内部的四个核心组件是松耦合的,Feather只是把它们像搭积木一样搭在一起。

  1. http组件: cinatra
  2. ORM组件: ormpp
  3. 序列化组件: iguana
  4. html 模版: inja

Feather的使用

以一个简单的例子展示如何使用Feather,比如显示文章列表,几乎每个网站都有这个功能。

获取文章列表的功能很简单,它底层数据部分是一个文章表,业务逻辑层是获取这些列表,然后做html渲染。对外接口部分是一个http服务,前端后端交互的数据格式为json。为了简单起见就不考虑缓存之类的。

那么要实现这个文章列表功能用Feather怎么做呢?可以按照这些步骤去开发:

  1. 提供获取文章列表的http接口;
  2. 通过ORM提供数据库访问功能;
  3. 编写业务逻辑,根据用户请求获取文章列表并通过html模版做渲染;

接下来看看这些步骤具体是怎么做的。

获取文章列表的http接口

其中login接口是这样的:

接下来就可以测试这个http服务接口了,客户端只要发送一个http请求即可。比如发送一个这样的请求

http://127.0.0.1/get_article_list

服务器会自动路由到article_controller::get_article_list函数中,如果请求不对则会返回http错误给客户端。当服务器收到这样的请求之后就表明服务器提供的这个http服务是可用的。

接下来需要编写数据库部分的代码,由于有了ORM,所以你可以很方便地编写数据库部分的代码了,同样很简单。

通过ORM提供数据库访问功能

登录业务涉及到一个用户表,因此我们需要创建这个表,不过在创建数据库之前先确定你选用什么数据库,Feather的ORM支持mysql, postgresql和sqlite三种数据库,假设我们的数据库是mysql。我们可以通过下面的代码来创建一个用户表。

1.创建文章表

dao.create_table< article >将会在testdb数据库中自动创建一个article表,其中id字段是自增长的。

2.编写获取文章列表的逻辑(包含访问数据库)

访问数据库,序列化为json返回给客户端。

详细的例子你可以看github上的代码

Demo示例

我们用Feather开发了一个社区网站,地址在这里:http://120.78.135.113:8080/

Feather社区

致谢

Feather社区网站由我和网友XMH共同开发完成(花了两天的业余时间),XMH也是cinatra的忠实用户,不但贡献了很多代码,还提供了很多宝贵的建议,在此表示衷心的感谢!

XMH是一名热爱编程的程序猿,平时从事c++,web,移动端等开发。从事过游戏后台和APP开发。也是个忠实的mordern c++粉丝,追随着cpp的发展,喜欢通过元编程做一些小工具。热爱开源社区,也是开源项目feather的使用者,希望feather能为更多的开发者所使用,社区发展越来越好。

希望有更多人能加入进来把Feather完善得更好。

联系我们

purecpp@163.com

http://purecpp.org/

https://github.com/qicosmos/feather

一个更好的自动注册工厂

在几年前我介绍过一种C++11实现的自动注册工厂,这是工厂模式的一种优雅的实现。在这里我们需要明确一个概念就是工厂模式,它是如何优雅地解决一个产品族的创建问题。所谓产品族就是一个继承体系的产品,比如有一个产品Message,它是一个基类,有很多Message是从它派生而来的,比如有Message1,Message2,Message3…等很多产品。

这些产品的创建依赖于某个key,类似于这样:

这是一个典型的工厂方法,这种写法在产品不多的时候是没问题的,但是如果产品越来越多的时候,switch-case就会越来越长,导致难以维护。另外还存在一个问题,有的产品不是无参数的构造函数,如果有些产品依赖了不同的参数,那么这个工厂方法是无法满足需求的。

之前介绍的自动注册工厂解决了switch-case膨胀的问题,但是对于需要参数的产品的创建没有解决得很好,需要进一步改进。改进的办法是把参数作为factory的模板参数,这样就可以解决有参数需求的问题了。

下面是具体实现:

这是一个Messgae产品族的工厂类,有了这个类之后我们就可以很方便地创建各种产品了。下面是测试例子:

Message产品族有4类产品,有的是无参的,有的是多个参数的产品,现在都可以统一创建了,直接输入key和构造参数即可,这个key可以自行修改为int或者枚举变量。

需要注意的是msg4,因为它注册的时候提供了一个function,让function提供创建功能,以满足更灵活地需求。

有了这样一个工厂类之后我们就可以很好地解决产品族创建的问题了。你还可以基于此把它改成一个抽象工厂类,但我觉得你应该慎重考虑一下是否有必要,一般情况下工厂模式就够了,不需要引入更多的复杂性。