std :: bind и шаблонная функция с переменным числом аргументов - PullRequest
0 голосов
/ 28 ноября 2018

Возможно ли это вообще?

#include <iostream>
#include <functional>

enum class Enum {a, b, c };

class Dispatch {
    public:
    void check(uint16_t) { std::cout << "check 16\n"; }
    void check(uint32_t) { std::cout << "check 32\n"; }
    void check(uint64_t) { std::cout << "check 64\n"; }

    template<Enum E, typename... A>
    void event(A&&... args) {
        tag_event(Tag<E>(), std::forward<A>(args)...);
    }

    private:
    template<Enum E> struct Tag {};    
    void tag_event(Tag<Enum::a>, uint16_t) { std::cout << "a\n"; }
    void tag_event(Tag<Enum::b>, uint16_t) { std::cout << "b\n"; }
    void tag_event(Tag<Enum::c>, uint16_t) { std::cout << "c\n"; }
};

void exec(std::function<void()>&& func) { func(); }

int main() {
    Dispatch d;

    // all good    
    exec(std::bind(static_cast<void(Dispatch::*)(uint16_t)>(&Dispatch::check), &d, uint16_t()));
    exec(std::bind(static_cast<void(Dispatch::*)(uint32_t)>(&Dispatch::check), &d, uint32_t()));
    exec(std::bind(static_cast<void(Dispatch::*)(uint64_t)>(&Dispatch::check), &d, uint64_t()));

    // all good
    d.event<Enum::a>(uint16_t());
    d.event<Enum::b>(uint16_t());
    d.event<Enum::c>(uint16_t());

    // but how do we bind an event<> call?
    exec(std::bind(static_cast<void(Dispatch::*)(uint16_t)>(&Dispatch::event<Enum::a>), &d, uint16_t()));
}

Итак, я пытаюсь связать вызов метода шаблона variadic, но получаю следующую ошибку компилятора ...

In function 'int main()':
42:86: error: no matches converting function 'event' to type 'void (class Dispatch::*)(uint16_t) {aka void (class Dispatch::*)(short unsigned int)}'
13:10: note: candidate is: template<Enum E, class ... A> void Dispatch::event(A&& ...)

Anyпредложения за исключением разоблачения всех перегрузок тегов вместо этого?

1 Ответ

0 голосов
/ 28 ноября 2018

Я предлагаю пройти через лямбда-функцию, как предлагается в комментариях.

В любом случае, если вы хотите перейти на std::bind(), мне кажется, что возможное решение -

// ..................................................VVVVVVVV  <-- ad this
exec(std::bind(static_cast<void(Dispatch::*)(uint16_t const &)>
     (&Dispatch::event<Enum::a, uint16_t const &>), &d, uint16_t()));
// ...........................^^^^^^^^^^^^^^^^^^  <-- and this

Я имею в виду: вы должны выбрать метод event(), объясняя также полученный тип;Я предлагаю uint16_t const & (вместо uint16_t), который совместим с универсальной эталонной сигнатурой вашего метода event() (я полагаю, возможны и другие комбинации, но для uint16_t активируется семантика перемещения ... Полагаю, это излишне).

...