I have a couple of classes here the first being a class that stores std::function
type.
template<typename RES_TYPE, typename... ARG_TYPES>
struct Functor {
std::function<RES_TYPE( ARG_TYPES... )> call_back;
};
I have another class that will register an incoming function either from a function object, function pointer or a lambda and stores an instance of the class above and has another member function that will invoke it.
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... );
}
};
I'm struggling to get the syntax right to where I'm trying to pass in the values of the function when trying to invoke it. My main looks something like this:
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;
}
I can not seem to wrap my head around what I'm missing within the syntax. I've tried various other things but with this current setup as is I'm getting this compiler error from 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 ==========
I have an idea of what the compiler is telling me but I can not seem to get the syntax correct to store this lambda, then be able to invoke it. I'm trying to keep these classes as generic as possible so that it can accept lambdas, function objects or function pointers.
Solution
My code now looks like this and works fine!
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;
}
Expected Outputs:
8 12 Hello World Generic Programming
Actual Outputs:
8 12 Hello World Generic Programming
Progam Exit:
Code (0)
You are trying to invoke operator()(int, int)
on the Functor
instance named callback_
. Instead, you need to name the data member of this struct call_back
. Like this:
RES_TYPE call_back( ARG_TYPES... args ) {
return callback_.call_back( args... );
}