C++拾遗

作者: 龙遁流 | 来源:发表于2020-04-20 11:49 被阅读0次
    可变参数模板函数
    template <typename ...T>
    void f(T... args)
    {
        cout << sizeof...(args) <<endl;
    }
    
    省略号的作用
    • 声明一个参数包,可包含0到任意个模板参数
    • 在模板定义的右边,可将参数包展开成各个独立的参数
    参数包展开
    • 递归函数方式展开参数包
      • 参数包展开函数

        template <typename T, typename ...Args>
        void print(T head, Args... rest)
        {
            f(head);
            print(rest...);
        }
        
      • 递归终止函数

        当参数包展开到最后一个参数时递归为止

        template <typename T, typename E>
        void print(T t, E e)
        {
        } 或
        void print()
        {
        }
        
      • 其他示例

      template <std::size_t I = 0, typename Tuple>
      typename std::enable_if <I == std::tuple_size<Tuple>::value>::type
      print(Tuple t)
      {
      }
      
      template <std::size_t I = 0, typename Tuple>
      typename std::enable_if <I < std::tuple_size<Tuple>::value>::type
      print(Tuple t)
      {
          std::count <<std::get<I>(t) <<std::endl;
          print<I + 1>(t);
      }
      
      template <typename ...Args>
      void printtp(Args... args)
      {
          print(std::make_tuple(args...));
      }
      
    • 逗号表达式和初始化列表方式展开参数包
      template <typename T>
      void print(T t){}
      
      template <typename ...Args>
      void expand(Args... args)
      {
           int arr[] = { (print(args), 0)... };
           
           std::initializer_list<int>
           {
              (print(arg), 0)... 
           };
           
           std::initializer_list<int>
           {
               ([&]{}(), 0)...
           };
      }
      
    可变参数模板类
    template<class ...Args>
    class tuple;
    
    模板递归和特化方式展开参数包
    //类声明
    template <typename ...Args> 
    struct Sum;
    //递归展开
    template <typename First, typename ...Rest>
    struct Sum<First, Rest...>
    {
        enum
        {
            value = Sum<First>::value + Sum<Rest...>::value
        };
    }
    //递归终止
    template <typename Last>
    struct Sum<Last>
    {
        enum
        {
            value = sizeof(Last)
        };
    }
    

    使用 std::integral_constant消除枚举定义value ,上例可修改为

    template <typename ...Args>
    struct Sum;
    
    template <typename First, typename ...Rest>
    struct Sum<First, Rest...> :
        std::integral_constant<int, Sum<First>::value + Sum<Rest...>::value>
    {
    }
    
    template <typename Last>
    struct Sum<Last> : 
        std::integral_constant<int, sizeof(Last)>
    {
    }
    
    Sum<int, double, short>::value;
    
    继承方式展开参数包

    内存对齐的缓冲区
    template <std::size_t Len, std::size_t Align = /*default-alignment*/>
    struct aligned_storage;
    
    • Len 存储类型的大小,sizeof(T)
    • Align 该类型内存对齐的大小,alignof(T)或者std::alignment_of<T>::value
    使用
    struct A
    {
        int avg;    
    }
    using Aligned_A = std::aligned_storage<sizeof(A), std::alignment_of<A>::value>::type;
    int main()
    {
        Aligned_A a, b;
        new (&a) A();
        b = a;
        cout << reinterpret_cast<A&>(b).avg<<endl;
        
        return 0;
    }
    

    可变模板参数和type_taits综合应用
    • optional
    • 惰性求值
    • std::result_of函数返回值类型推断
    • dll帮助类
    • lambda链式调用
    template <typename T>
    class Task;
    
    template<typename R, typename ...Args>
    class Task<R(Args...)>
    {
        public:
            Task(std::function<R(Args...)> &&f) : m_fn(std::move(f)){}
            Task(std::function<R(Args...)> &f) : m_fn(f){}
            
            R Run(Args&&... args)
            {
                return m_fn(std::forward<Args>(args)...);
            }
            
            template<typename F>
            auto Then(F &&f) -> Task<typename std::result_of<F(R)>::type(Args...)>
            {
                using return_type = typename std::result_of<F(R)>::type;
                auto func = std::move(m_fn);
                return Task<return_type(Args...)>([func, &f] (Args&&... args)
                {
                    return f(func(std::forward<Args>(args)...));
                };
            }
        private:
            std::function<R(Args...)> m_fn;
    }
    
    {
    Task<int(int)> task([](int i){return i});
    auto result = task.Then([](int i){return i + 1})
                      .Then([](int i){return i + 2})
                      .Then([](int i){return i + 3})
                      .Run(1);
    }
    
    • any类的实现 (只能容纳一个元素,可擦出类型,可赋给它任何类型的值)
    • function_traits
    • variant 类似于union
    • ScopeGuard (确保资源对非正常返回时可以正确释放,RAII)
    • tuple_helper

    • shared_ptr使用默认删除器销毁数组
      std::default_delete<T[]>
    • 不要使用原始指针初始化多个shared_ptr
    • 不要在函数实参中创建shared_ptr,由于函数调用约定可能造成资源泄露
    • 正确返回thisshared_ptr
      class A : public std::enable_shared_from_this<A>
      {
          std::shared_ptr<A> GetSelf()
          {
              return shared_from_this();
          }
      }
      
    • 避免循环引用
      {
          shared_ptr<A> ap(new A);
          shared_ptr<B> bp(new B);
          ap->bptr = bp;
          bp->aptr = ap;
      }
      
      析构的时候,A和B都要依赖对方先析构后才析构自己,这样循环依赖就都不会析构。使用weak_ptr可解决。
    • unique_ptr 不允许复制,但可以通过move语义移动;但可以通过函数返回给其他unique_ptr
    • unique_ptr 允许指向数组,而shared_ptr不可以
      shared_ptr<int> p(new int[10], default_delete<int[]>());
      
      unique_ptr<int[]> ptr(new int[10]);
      //指定删除器
      unique_ptr<int, void(*)(int*)> ptr(new int(1), [](int *p){delete p;});
      unique_ptr<int, function<void(int*)>> ptr(new int(1), [&](int *p){delete p;});
      unique_ptr<int, MyDelete> ptr(new int(1));
      
    • lambda在没有捕获变量的情况下是可以直接转换为函数指针的
    • weak_ptr是用来监视shared_ptr的生命周期的,不会使引用计数加1。监视shared_ptr的资源是否存在,可用来返回this指针和解决循环引用。
      • use_count()获取其观测的引用计数
      • expired()观测的资源是否已被释放
      • lock()获取观测的shared_ptr对象

    相关文章

      网友评论

        本文标题:C++拾遗

        本文链接:https://www.haomeiwen.com/subject/jrrwbhtx.html