C++ lambda with captures as a function pointer

后端 未结 8 795
离开以前
离开以前 2020-11-22 15:35

I was playing with C++ lambdas and their implicit conversion to function pointers. My starting example was using them as callback for the ftw function. This works as expecte

相关标签:
8条回答
  • 2020-11-22 16:01

    Hehe - quite an old question, but still...

    #include <iostream>
    #include <vector>
    #include <functional>
    
    using namespace std;
    
    // We dont try to outsmart the compiler...
    template<typename T>
    int ftw(const char *fpath, T callback) {
      return callback(fpath);
    }
    
    int main()
    {
      vector<string> entries;
    
      // ... now the @ftw can accept lambda
      int ret = ftw("/etc", [&](const char *fpath) -> int {
        entries.push_back(fpath);
        return 0;
      });
    
      // ... and function object too 
      struct _ {
        static int lambda(vector<string>& entries, const char* fpath) {
          entries.push_back(fpath);
          return 0;
        }
      };
      ret = ftw("/tmp", bind(_::lambda, ref(entries), placeholders::_1));
    
      for (auto entry : entries ) {
        cout << entry << endl;
      }
    
      return ret;
    }
    
    0 讨论(0)
  • 2020-11-22 16:02

    Using locally global (static) method it can be done as followed

    template <class F>
    auto cify_no_args(F&& f) {
      static F fn = std::forward<F>(f);
      return [] {
        return fn();
      };
    }
    

    Suppose we have

    void some_c_func(void (*callback)());
    

    So the usage will be

    some_c_func(cify_no_args([&] {
      // code
    }));
    

    This works because each lambda has an unique signature so making it static is not a problem. Following is a generic wrapper with variadic number of arguments and any return type using the same method.

    template <class F>
    struct lambda_traits : lambda_traits<decltype(&F::operator())>
    { };
    
    template <typename F, typename R, typename... Args>
    struct lambda_traits<R(F::*)(Args...)> : lambda_traits<R(F::*)(Args...) const>
    { };
    
    template <class F, class R, class... Args>
    struct lambda_traits<R(F::*)(Args...) const> {
        using pointer = typename std::add_pointer<R(Args...)>::type;
    
        static pointer cify(F&& f) {
            static F fn = std::forward<F>(f);
            return [](Args... args) {
                return fn(std::forward<Args>(args)...);
            };
        }
    };
    
    template <class F>
    inline lambda_traits<F>::pointer cify(F&& f) {
        return lambda_traits<F>::cify(std::forward<F>(f));
    }
    

    And similar usage

    void some_c_func(int (*callback)(some_struct*, float));
    
    some_c_func(cify([&](some_struct* s, float f) {
        // making use of "s" and "f"
        return 0;
    }));
    
    0 讨论(0)
提交回复
热议问题