Variadic Templates, std :: function и lambdas как члены класса - PullRequest
0 голосов
/ 24 октября 2018

У меня есть пара классов, первый из которых является классом, в котором хранится тип std::function.

template<typename RES_TYPE, typename... ARG_TYPES>
struct Functor {
    std::function<RES_TYPE( ARG_TYPES... )> call_back;
};

У меня есть другой класс, который регистрирует входящую функцию из объекта функции, указателя функции илилямбда и хранит экземпляр класса выше и имеет другую функцию-член, которая будет вызывать его.

template<typename RES_TYPE, typename... ARG_TYPES>
class Driver {
private:
    Functor<RES_TYPE, ARG_TYPES...> callback_;

public:
    Driver() = default;
    ~Driver() = default;

    void register_callback( const Functor<RES_TYPE, ARG_TYPES...> &func ) {
        callback_ = func;
    }

    RES_TYPE call_back( ARG_TYPES... args ) {
        return callback_( args... );
    }    
};

Я пытаюсь получить синтаксис там, где я пытаюсь передать значенияфункция при попытке вызвать его.Моя главная выглядит примерно так:

int main() {    
    Functor<int, int, int> func;
    auto lambda = []( int a, int b ) { return a + b; };
    func.call_back = lambda;

    Driver<int, int, int> driver;
    driver.register_callback( func );
    std::cout << driver.call_back( 3, 5 ) << '\n';

    return 0;
}

Кажется, я не могу обернуть голову вокруг того, что мне не хватает в синтаксисе.Я пробовал разные другие вещи, но с этой текущей установкой, как я получаю эту ошибку компилятора из Visual Studio 2017 CE:

1>------ Build started: Project: Temp, Configuration: Debug Win32 ------
1>main.cpp
1>c:\...\main.cpp(62): error C2064: term does not evaluate to a function taking 2 arguments
1>c:\...\main.cpp(62): note: while compiling class template member function 'RES_TYPE Driver<RES_TYPE,int,int>::call_back(int,int)'
1>        with
1>        [
1>            RES_TYPE=int
1>        ]
1>c:\...\main.cpp(77): note: see reference to function template instantiation 'RES_TYPE Driver<RES_TYPE,int,int>::call_back(int,int)' being compiled
1>        with
1>        [
1>            RES_TYPE=int
1>        ]
1>c:\...\main.cpp(75): note: see reference to class template instantiation 'Driver<int,int,int>' being compiled
1>Done building project "Temp.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

У меня есть представление о том, что говорит мне компилятор, но я могуПохоже, что синтаксис не будет правильным для хранения этой лямбды, тогда можно будет вызывать ее.Я пытаюсь сделать эти классы настолько универсальными, насколько это возможно, чтобы они могли принимать лямбды, функциональные объекты или указатели функций.


Решение

Мой код сейчасвыглядит так и работает отлично!

template<typename RES_TYPE, typename... ARG_TYPES>
struct Functor {
    std::function<RES_TYPE( ARG_TYPES... )> func_;
};

template<typename RES_TYPE, typename... ARG_TYPES>
class Driver {
private:
    Functor<RES_TYPE, ARG_TYPES...> functor;

public:
    Driver() = default;
    ~Driver() = default;

    void register_callback( const Functor<RES_TYPE, ARG_TYPES...> &func ) {
        functor = func;
    }

    RES_TYPE call_back( ARG_TYPES... args ) {
        return functor.func_( args... );
    }    
};

int main() {    
    Functor<int, int, int> func;
    auto lambda = []( int a, int b ) { return a + b; };
    func.func_ = lambda;

    Driver<int, int, int> driver;
    driver.register_callback( func );
    int a = 3;
    int b = 5;
    std::cout << driver.call_back( a, b ) << '\n';
    std::cout << driver.call_back( 7, 5 ) << '\n';

    Functor<void, std::string, std::string> func2;
    auto lambda2 = []( std::string str1, std::string str2 ) {
        str1 = str1 + " " + str2;
        std::cout << str1 << '\n';
    };

    Driver <void, std::string, std::string> driver2;
    func2.func_ = lambda2;
    std::string str1 = "Hello";
    std::string str2 = "World";
    driver2.register_callback( func2 );
    driver2.call_back( str1, str2 );
    driver2.call_back( "Generic", "Programming" );

    return 0;
}

Ожидаемые выходы:

8
12
Hello World
Generic Programming

Фактические выходы:

8
12
Hello World
Generic Programming

Выход Progam:

Code (0)

1 Ответ

0 голосов
/ 24 октября 2018

Вы пытаетесь вызвать operator()(int, int) для экземпляра Functor с именем callback_.Вместо этого вам нужно назвать элемент данных этой структуры call_back.Как это:

RES_TYPE call_back( ARG_TYPES... args ) {
    return callback_.call_back( args... );
}
...