Шаблонный необязательный конструктор аргумента с обратным вызовом параметра void - PullRequest
1 голос
/ 27 января 2020

Я ищу написать такой класс, чтобы он мог хранить часть данных и передавать их через лямбду. Я также хотел бы иметь возможность не передавать значение в конструктор, и чтобы конструктор генерировал лямбду без параметра. Я в порядке, у меня все еще есть часть данных в классе.

Я пытался использовать опциональные параметры и использовать параметр шаблона по умолчанию типа void, но не смог заставить его работать. Самое близкое, что я получил, было это.

template<class T = void>
class X {
   std::optional<T> d;       // data present or garbage data
   std::function<void(T)> f; // parameter = type of data or void if no arg provided
public:
   X(std::optional<T> a, std::function<void(T)> b) : d{a}, f{b} {}
   a() {
      if (d.has_value()) f(d);
      else f();
   }
}

Надеясь на работу конструктора, как

X(5, [&](int x) {}); // where the int type is implied from the constructor

ИЛИ

X([&](){}); // where the lack of parameter implies the function parameter is void

Спасибо.

РЕДАКТИРОВАТЬ: предоставил пример попытки создания класса самостоятельно. РЕДАКТИРОВАТЬ 2: попытался прояснить необходимость хранить и вызывать функцию позднее.

1 Ответ

3 голосов
/ 27 января 2020

Вы можете использовать что-то вроде этого:

#include <iostream>
#include <functional>

void foo() {
    std::cout << "void foo()" << std::endl;
}

void bar(int x) {
    std::cout << "void foo(int x) with parameter x = " << x << std::endl;
}

class X {
public:
    template <typename F, typename ... Args>
    X(F&& f, Args&&... args) {
        std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
    }
};

int main() {
    X a(foo);
    X b(bar, 1);
    X c([&](int x, int y) {
        std::cout << "lambda with parameters x = " << x << " y = " << y << std::endl;
    }, 1, 2);

    return 0;
}

Check live

В основном, используя предоставленный класс X, вы можете отправлять любую функцию, которую хотите ( освободите функцию, лямбда и т. д. c.) и передайте любое количество параметров по вашему желанию.

ОБНОВЛЕНИЕ

В соответствии с комментарием ОП и wi sh для сохранить лямбду и аргументы для члена класса и вызвать его позже, вот обновленный код:

#include <iostream>
#include <tuple>
#include <functional>

template <typename F, typename ... Args>
class X {
public:
    X(F&& f, Args&&... args)
        : f_(std::forward<F>(f)),
          args_(std::forward<Args>(args)...)
    {}

    void call() {
        std::apply(f_, args_);
    }

private:
    F f_;
    std::tuple<Args...> args_;
};

int main() {
    X c([&](int x, int y) {
        std::cout << "lambda with parameters x = " << x << " y = " << y << std::endl;
    }, 1, 2);

    c.call();

    return 0;
}

Check live

...