equivalent implementation of C++20 variadic capture

50 views Asked by At

Out of pure curiosity, while watching C++ weekly ep 171 I was wondering how variadic capture could be implemented, so I merely "asked" cppinsight. Here is the input snippet:

#include <utility>

template <typename C, typename... A>
auto bind_values(C callable, A... args) {
    return [callable = std::move(callable), ... my_param = std::move(args)]() {
        return callable(my_param...);
    };
}

int add(int lhs, int rhs) { return lhs + rhs; }

int main() {
    const auto bound = bind_values(add, 1, 2);
    return bound();
}

And the output of cppinsight (only the relevant part):

  class __lambda_6_12
  {
    public: 
    inline auto operator()() const
    {
      return callable(my_param... );
    }
    
    private: 
    auto callable;
    auto... my_param;
    
    public:
    __lambda_6_12(auto _callable, auto const &... _my_param)
    : callable{_callable}
    , my_param{_my_param...}
    {}
    
  } __lambda_6_12{std::move(callable), std::move(args)};

I was surprised to see member variables declared with auto and even auto... and expected tuple instead (for instance).
Is it merely that cppinsight don't necessarily produced valid cpp code (but only a pseudo code) or is it real C++? I would be inclined to believe the first solution, as trying to compile the cppinsight code fails and I can't see how it could work anyway.

My version would more look like this:

#include <tuple>
template <typename C, typename... A>
class __lambda_6_12 {
   public:
    inline auto operator()() const { return callable(my_param...); }

   private:
    C callable;
    std::tuple<A...> my_param;

   public:
    __lambda_6_12(C _callable, A const &..._my_param)
        : callable{_callable}, my_param{_my_param...} {}
};

Which seems to better suit the compiler. (note my operator() above is wrong, the tuple should be expanded again into a pack, and the pack passed to callable)

0

There are 0 answers