JoungCPPser
JoungCPPser

Reputation: 41

C++: store list of lambda functions

I need to create a vector that will store void functions with different number of parameters. I used variadic templates for this, but it doesn't work.

#include <iostream>
#include <functional>

template<class...Types>
using MyFun = std::function<void(Types...)>;

std::vector<MyFun<>> operators;

template<class Lambda>
void addOperator(Lambda lambda)
{
    operators.emplace_back(lambda);
}

int main()
{
    auto f1 = [](int a, int b){std::cout<<a+b;};
    auto f2 = [](double a, double b){std::cout<<a+b;};
    addOperator(f1);
    addOperator(f2);

    return 0;
}

Can you help me?

Upvotes: 2

Views: 733

Answers (2)

user1095108
user1095108

Reputation: 14603

You need anyfunc, which is an upgraded std::any, that allows invocation. You can just do:

std::vector<gnr::anyfunc> v;

Just like you would with a std::any, but you need to remember the exact function signature of the functor you stored, though this can be hacked around, if you write your own anyfunc. Anyway, here's an example.

std::vector<gnr::anyfunc<>> v{
  [&](){ std::cout << "yay" << std::endl; },
  [&](int const i) { std::cout << i << std::endl; }
};

v[0]();
v[1](1);

But this is just one example. You can even store coroutines in lists without any problems.

Upvotes: 0

Aykhan Hagverdili
Aykhan Hagverdili

Reputation: 29985

Assuming you have a small number of possible types, here's an example:

#include <stdio.h>

#include <variant>
#include <vector>

// this helper is from https://en.cppreference.com/w/cpp/utility/variant/visit
template <class... Ts>
struct overloaded : Ts... {
  using Ts::operator()...;
};

template <class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;

int main() {
  using T1 = void (*)(int, int);
  using T2 = void (*)(double, double);

  T1 const f1 = [](int a, int b) { printf("int add: %d\n", a + b); };
  T2 const f2 = [](double a, double b) { printf("double add: %f\n", a + b); };

  std::vector<std::variant<T1, T2>> vec{f1, f2};
  // add more elements if needed

  for (auto const& f : vec) {
    // example usage
    std::visit(overloaded([](T1 const& f) { f(1, 2); },
                          [](T2 const& f) { f(1.5, 2.3); }), f);
  }
}

Upvotes: 4

Related Questions