热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++11实现golang的defer类似Javafinally操作。

Copyright2013<chaishushan#gmail.com>.Allrightsreserved.Useofthissourcecod
// Copyright 2013 . All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#ifndef _DEFER_H_
#define _DEFER_H_

#include 
#include 

//
// 需要支持C11 -std=c++11
// defer 语句定义一个延迟执行闭包函数的对象
//
// 基于用法:
//
//  FILE* fp = fopen("foo.txt", "rt");
//  if(fp == NULL) return false;
//  defer([&](){ printf("fclose(fp)\n"); fclose(fp); });
//  
//  char* buf = new char[1024];
//  defer([&](){ printf("delete buf\n"); delete[] buf; });
//  
//  defer([](){ printf("defer a: %d\n", __LINE__); });
//  defer([](){ printf("defer a: %d\n", __LINE__); });
//  defer([](){ printf("defer a: %d\n", __LINE__); });
//  
//  {
//      defer([](){ printf("defer b: %d\n", __LINE__); });
//      defer([](){ printf("defer b: %d\n", __LINE__); });
//      defer([](){ printf("defer b: %d\n", __LINE__); });
//  }
//  
//  defer([](){
//      printf("defer c:\n");
//      for(int i = 0; i <3; ++i) {
//          defer([&](){ defer([&](){
//              printf("\ti = %d: begin\n", i);
//              defer([&](){ printf("\ti = %d\n", i); });
//              printf("\ti = %d: end\n", i);
//          });});
//      }
//  });
//
// 注意事项:
//
// 1. defer 定义的对象在超出作用域时执行闭包函数(析构函数)
// 2. defer 定义的对象在同一个文件内部标识符不同(根据行号生成)
// 3. defer 在全局作用域使用可能会出现重名现象(行号相同)
// 4. defer 在判断语句使用可能提前执行(作用域结束时)
// 5. defer 在循环语句内使用无效(作用域结束时)
// 6. defer 和Go语言的defer并不完全等价
//
// 更多参考:
//
// http://blog.korfuri.fr/post/go-defer-in-cpp/
// http://blog.korfuri.fr/attachments/go-defer-in-cpp/defer.hh
// http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
// http://golang.org/doc/effective_go.html#defer
// http://golang.org/ref/spec#Defer_statements
//

#define defer _DEFER_ACTION_MAKE /* ([&](){ ... }); */

// auto _defer_action_line???_ = _DeferredActionCtor([&](){ ... })
#define _DEFER_ACTION_MAKE auto \
    _DEFER_ACTION_VAR(_defer_action_line, __LINE__, _) = _DeferredActionCtor
#define _DEFER_ACTION_VAR(a, b, c) _DEFER_TOKEN_CONNECT(a, b, c)
#define _DEFER_TOKEN_CONNECT(a, b, c) a ## b ## c

// 持有闭包函数
class _DeferredAction {
private:
    std::function func_;

    template
    friend _DeferredAction _DeferredActionCtor(T&& p);

    template
    _DeferredAction(T&& p): func_(std::bind(std::forward(p))) {
        std::cout <<"NEW 1" <>(other.func_)) {
        other.func_ = nullptr;
        std::cout <<"NEW 2" <
_DeferredAction _DeferredActionCtor(T&& p) {
    return _DeferredAction(std::forward(p));
}

#endif  // _DEFER_H_



测试:


/* 
 * File:   main.cpp
 * Author: Vicky.H
 * Email:  eclipser@163.com
 */
#include "defer.h"
#include 


void sayHello(const char* name) {
    printf("hello %s\n", name);
}


void funTest() {
    printf("funTest 1\n");
    defer([]() {
        printf("defer c: %d\n", __LINE__); });
    defer([]() {
        printf("defer c: %d\n", __LINE__); });
    defer([]() {
        printf("defer c: %d\n", __LINE__); });
    printf("funTest 2\n");
}

/*
 * 
 */
int main(void) {
    defer([]() {
        printf("defer a: %d\n", __LINE__); });
    defer([]() {
        printf("defer a: %d\n", __LINE__); });
    defer([]() {
        printf("defer a: %d\n", __LINE__); });
    defer([](){
        sayHello("jack"); });

    {
        defer([](){ printf("defer b: %d\n", __LINE__); });
        defer([](){ printf("defer b: %d\n", __LINE__); });
        defer([](){ printf("defer b: %d\n", __LINE__); });
        std::cout <<"in code scope" < 
 

git: http://git.oschina.net/eclipser/defer4cpp.git


注意,以上代码需要支持C++11  : -std=c++11


输出:

NEW 1
NEW 1
NEW 1
NEW 1
NEW 1
NEW 1
NEW 1
in code scope
defer b: 42
DELETE
defer b: 41
DELETE
defer b: 40
DELETE


---------------------------
Done 1
Done 2
Done 3


---------------------------
funTest 1
NEW 1
NEW 1
NEW 1
funTest 2
defer c: 22
DELETE
defer c: 20
DELETE
defer c: 18
DELETE
hello jack
DELETE
defer a: 35
DELETE
defer a: 33
DELETE
defer a: 31
DELETE


运行 FINISHED; 退出值0; 实时:  20ms; 用户:  0ms; 系统:  0ms



推荐阅读
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Jboss的EJB部署描述符standardjaws.xml配置步骤详解
    本文详细介绍了Jboss的EJB部署描述符standardjaws.xml的配置步骤,包括映射CMP实体EJB、数据源连接池的获取以及数据库配置等内容。 ... [详细]
  • Oracle 和 mysql的9点区别【MySQL】
    数据库|mysql教程oracle,Oracle,money,mysql,coun数据库-mysql教程1.组函数用法规则mysql中组函数在select语句中可以随意使用,但在o ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • PHPMailer邮件类邮件发送功能的使用教学及注意事项
    本文介绍了使用国外开源码PHPMailer邮件类实现邮件发送功能的简单教学,同时提供了一些注意事项。文章涵盖了字符集设置、发送HTML格式邮件、群发邮件以及避免类的重定义等方面的内容。此外,还提供了一些与PHP相关的资源和服务,如传奇手游游戏源码下载、vscode字体调整、数据恢复、Ubuntu实验环境搭建、北京爬虫市场、进阶PHP和SEO人员需注意的内容。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • JavaScript和HTML之间的交互是经由过程事宜完成的。事宜:文档或浏览器窗口中发作的一些特定的交互霎时。能够运用侦听器(或处置惩罚递次来预订事宜),以便事宜发作时实行相应的 ... [详细]
  • 手把手教你使用GraphPad Prism和Excel绘制回归分析结果的森林图
    本文介绍了使用GraphPad Prism和Excel绘制回归分析结果的森林图的方法。通过展示森林图,可以更加直观地将回归分析结果可视化。GraphPad Prism是一款专门为医学专业人士设计的绘图软件,同时也兼顾统计分析的功能,操作便捷,可以帮助科研人员轻松绘制出高质量的专业图形。文章以一篇发表在JACC杂志上的研究为例,利用其中的多因素回归分析结果来绘制森林图。通过本文的指导,读者可以学会如何使用GraphPad Prism和Excel绘制回归分析结果的森林图。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
  • Linux下部署Symfoy2对app/cache和app/logs目录的权限设置,symfoy2logs
    php教程|php手册xml文件php教程-php手册Linux下部署Symfoy2对appcache和applogs目录的权限设置,symfoy2logs黑色记事本源码,vsco ... [详细]
  • html和js代码互转,html转html5
    本文目录一览:1、html网页跳转javascript代码实现 ... [详细]
author-avatar
手机用户2502915433
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有