Modern C++的应用,实现golang中的defer

modern C++实现 golang 的defer

关于RAII的一些思考。

defer 的简介

注:没有 golang 语法基础的读者可以看看,反之,可以跳过。

golang语法中的defer是什么?

defer用来声明一个延迟函数,把这个函数放入到一个栈上, 当外部的包含方法return之前,返回参数到调用方法之前调用,也可以说是最外层方法体执行结束时调用。

举一个简单的例子,在函数test()中用defer声明在函数结束后执行打印Exit function -> test()

package main
import "fmt"

func test() {
    defer fmt.Println("Exit function -> test()")
    fmt.Println("Enter function -> test()")
}

func main() {
    test()
}

执行结果:

Enter function -> test()
Exit function -> test()

涉及 modern C++ 语法简介

auto

C++11标准之前的是auto含义的分割线,之前的auto没有什么实际的含义,仅仅代表除了static之外的存储属性。之后的auto用于编译器自动推导变量类型,用auto初始化的变量编译器会自动推导其类型。

需要注意的是:

  • auto定义变量的时候没有缺省值。下面这样的代码就会报错:

    auto value;
    
  • auto定义的变量第一次推导出变量的类型就不会在自动更改,比如下面这样的代码编译器就会有警告:

    auto value = 10;
    value = 1.2; // Warning: implicit conversion from 'double' to 'int' 
    			 // changes value from 1.2 to 1
    

几个小例子:

注:读者感兴趣的话,请自行在MSVC编译器下编译,因为MSVC编译出的这段代码可视性能好一点。博主刚把MSVC卸载了,暂时也没有windows下的C/C++编译环境。

#include 
#include 

// 读者先不必理会这是个什么东西,这个只是用来打印分割线的
auto divider = [] {
    for(auto i = 0; i < 10; ++i) std::cout << '--';
    std::cout << std::endl;
}

int main() { 
	auto value_1 = 10;
    std::cout << "value_1: " << value_1 << std::endl;
    std::cout << "value_1 type is: " << typeid(value_1).name() << std::endl;
    divider();
	auto value_2 = 1.2;
    std::cout << "value_2: " << value_2 << std::endl;
    std::cout << "value_2 type is: " << typeid(value_2).name() << std::endl;
    divider();
	auto value_3 = &value_1;
    std::cout << "value_3: " << value_3 << std::endl;
    std::cout << "value_3 type is: " << typeid(value_3).name() << std::endl;
    return 0;
}

lambda

详细用法和介绍可以看看这个:c++中的可调用对象

博主这里的代码采用MSVC编译器编译,因为它编译出的 typeid(value).name() 比g++的可视性更好一些。

lambda 用来定义一个可调用对象,也可以说是匿名函数。

#include 
#include 
// 注:MSVC编译器可以不用包含typeinfo,g++编译器必须包含才能使用typeid
// #include   

// 定义一个匿名函数对象赋值给 func_args
auto func_args = [](const std::string& s) {
    std::cout << s << std::endl;
}

// 定义一个匿名函数对象赋值给 func_non_args
auto func_non_args = [] {
    std::cout << "call func_non_args..." << std::endl;
}

int main() {
    std::cout << "func_args type is: " << typeid(func_args).name() << std::endl;
    func_args("call func_args...");
    std::cout << "func_args type is: " << typeid(func_non_args).name() << std::endl;
    func_non_args();
    return 0;
}

执行结果:

func_args type is: class 
call func_args...
func_non_args type is: class 
call func_non_args...

右值引用

//TODO

std::move

//TODO

std::foraward

//TODO

具体实现

预览

我想要实现的最终效果:

#include 

func test() {
    // DEFER 换成小写也可以
    DEFER { std::cout << "Exit function -> test()" << std::endl; };
    std::cout << "Enter function -> test()" << std::endl;
}

int main() {
    test();
}

执行结果:

Enter function -> test()
Exit function -> test()

设计过程

//TODO

最终结果

#include 

template <typename T>
class _Defer {
  public:
    _Defer(T&& d) : _d(std::move(d)){}  // 移动语义
    ~_Defer() { _d(); }
  private:
    T _d;
};

class Defer {
  public:
    template <typename T>
    _Defer<T> operator+(T&& d) {
      return _Defer<T>(std::forward<T>(d));  // 完美转发
    }
};

#define CONCAT_IMPL(prefix, suffix) prefix##suffix  //宏连接
#define CONCAT(perfix, suffix) CONCAT_IMPL(prefix, suffix)
#define UNIQUE_NAME(prefix) CONCAT(prefix, __COUNTER__)
#define DEFER auto UNIQUE_NAME(defer_) = Defer() + [&] //lambda表达式

void test() {
  // 在test()函数推出后打印 “func exit!”
  DEFER { std::cout << "func exit!" << std::endl;  };
}

int main(){
  std::cout << "Call test() function..." << std::endl;
  test();
  return 0;
}

你可能感兴趣的:(C/C++语言)