C++11实现golang的defer类似Java finally操作。
2014-01-20 17:05
381 查看
// Copyright 2013 <chaishushan#gmail.com>. 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 <functional> #include <iostream> // // 需要支持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<void()> func_; template<typename T> friend _DeferredAction _DeferredActionCtor(T&& p); template<typename T> _DeferredAction(T&& p): func_(std::bind(std::forward<T>(p))) { std::cout << "NEW 1" << std::endl; } _DeferredAction(); _DeferredAction(_DeferredAction const&); _DeferredAction& operator=(_DeferredAction const&); _DeferredAction& operator=(_DeferredAction&&); public: _DeferredAction(_DeferredAction&& other): func_(std::forward<std::function<void()>>(other.func_)) { other.func_ = nullptr; std::cout << "NEW 2" << std::endl; } ~_DeferredAction() { if(func_) { func_(); } std::cout << "DELETE" << std::endl; } }; template<typename T> _DeferredAction _DeferredActionCtor(T&& p) { return _DeferredAction(std::forward<T>(p)); } #endif // _DEFER_H_
测试:
/* * File: main.cpp * Author: Vicky.H * Email: eclipser@163.com */ #include "defer.h" #include <iostream> 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" << std::endl; } std::cout << "\n---------------------------" << std::endl; std::cout << "Done 1" << std::endl; std::cout << "Done 2" << std::endl; std::cout << "Done 3" << std::endl; // throw "exception happen"; std::cout << "\n---------------------------" << std::endl; funTest(); return 0; }
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
相关文章推荐
- Xftp 与ftp 类似,安全性要较高。java实现操作sftp需要第三方的jar包,本例使用
- 使用Java中JTextArea实现类似命令行操作的界面
- java实现类似与redis的hash存储操作
- Java中单点登录的实现——类似QQ“顶号”操作
- 用java简单的实现单链表的基本操作
- Java平台要实现类似豆丁百度文科的文档在线阅读,总体思路是讲doc docx等文件格式利用jcom转换成pdf再用swftools转为swf。再用flexpaper组件显示swf。
- java实现使用JDBC-ODBC桥操作数据库。
- java实现安全证书相关操作
- jldap实现Java对LDAP的基本操作
- Java实现二叉树的基本操作
- Java实现用Mysql存取图片操作实例
- Java实现的生成二维码和解析二维码URL操作示例
- 数据结构(二):Java实现:链表实现增删查操作(具有头结点)
- java 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
- Java实现HDFS文件操作工具类
- java语言实现简单单链表链式储存结构。插入删除等操作。(有个地方看不出错误来,已经标注,望指正)
- 【LeetCode-面试算法经典-Java实现】【225-Implement Stack using Queues(用队列实现栈操作)】
- MongoDB学习系列12:Java实现对MongoDB的AND、OR和IN操作
- Java项目中操作提示的简单实现
- java中不用BigInteger实现超大整数的乘法操作