一些关于C++编程的小技巧

本文最后更新于:2023年11月19日 早上

近些日子在C++开发过程中总结了一些小技巧,在这里记录下来。

  • 一个接受具有任意参数列表的函数指针,同时接收对应的参数的函数,打包成一个可执行的lambda以在之后执行。
    • 示例代码:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      // 引入std::function以便于打包lambda
      #include <functional>

      // 将参数列表作为模板参数包
      template <typename ...args>
      std::function<void()> reciever(void (*func)(args...), args... arguments)
      {
      // 在lambda中使用外部变量,这里是在编译期就推导出来的函数。
      return [=](){
      func(arguments...);
      };
      }
  • 在上一个函数的基础上,将参数储存在一个以std::string为键的std::map中,在调用时传入相应的std::string。
    • 示例代码:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      #include <functional>

      #include <string>
      #include <map>
      #include <any>

      class caller
      {
      private:
      std::map<std::string, std::any> argumentPool;

      template <typename T>
      static T& convert(std::any &obj)
      {
      return std::any_cast<T&>(obj);
      }
      public:
      caller() = default;
      ~caller() = default;

      template <typename T>
      void setArg(const std::string &name, const T &copy = T())
      {
      argumentPool[name] = copy;
      }

      template <typename T>
      T& getArg(const std::string &name)
      {
      return convert<T>(argumentPool.at(name));
      }

      // 这里同时使用了两个模板参数包,仅在模板参数自动推导时可以正常识别两个参数包应有的参数。
      template <typename ...args, typename ...names>
      std::function<void()> getCaller(void (*func)(args...), names... argNames)
      {
      return [=, &argumentPool](){
      func(convert<args>(argumentPool.at(argName))...);
      };
      }
      };
  • 多线程中对std::thread进行包装。
    • 示例代码:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      #include <thread>
      #include <functional>

      class Thread
      {
      private:
      // 工作线程以指针形式储存
      std::thread *worker;
      // 工作载荷在lambda中储存
      std::function<void()> work

      // 线程结束标记
      bool readyToClose;
      public:
      Thread():
      worker(NULL), readyToClose(false) {}
      ~Thread()
      {
      if (worker != NULL)
      {
      // 等待线程结束
      while (!readyToClose)
      std::this_thread::yield();
      delete worker;
      }
      }

      template <typename ...args>
      void setFunction(void (*func)(args...), args... arguments)
      {
      work = [=, &readyToClose](){
      func(arguments...);
      readyToClose = true;
      }
      }

      void run()
      {
      worker = new std::thread(work);
      worker->detach();
      }
      };

一些关于C++编程的小技巧
https://www.12hydrogen.dev/2023/10/15/A-summary-of-some-cpp-programing-skill/
作者
12Hydrogen
发布于
2023年10月15日
更新于
2023年11月19日
许可协议