i simplified the problem as much as i could so here is the function in question:
class Test
{
public:
template<class T>
void ExecuteFunction(std::function<void(T)> f)
{
}
};
if i call the function with int-typing everything works fine, however, if i call it with a void-typed lambda it doesn't compile anymore.
Test test;
test.ExecuteFunction<void>( // doesn't compile
[](void)->void
{
int i = 5;
});
test.ExecuteFunction<int>( // this compiles
[](int)->void
{
int i = 5;
});
Compiler errors:
Error C2672 'Test::ExecuteFunction': no matching overloaded function found
Error C2770 invalid explicit template argument(s) for 'void Test::ExecuteFunction(std::function<void(P)>)'
Error (active) no instance of function template "Test::ExecuteFunction" matches the argument list
is there a way around this? how would someone specify the template so that both calls work?
Sure, void
in parentheses is but a vintage C-style sugar. You'll have to specialize your template:
template<> void Test::ExecuteFunction<void>(std::function<void()> f) {}
If that does not compile, well, you can use a helper template to encapsulate the type-selection:
#include <iostream>
#include <functional>
template<class T> struct callable {
using type = std::function<void(T)>;
};
template<class T> using callable_t =
typename callable<T>::type;
template<> struct callable<void> {
using type = std::function<void()>;
};
class Test
{
public:
template<class T>
void ExecuteFunction(callable_t<T> f) {}
};
int main() {
Test test;
test.ExecuteFunction<void>( // does compile
[](void)->void {});
test.ExecuteFunction<int>( // this compiles
[](int)->void {});
}
But be aware that this way you'll have to also do something to the arguments passing (in your example, a generic case's argument is unary yet specialization for void
expects a nullary function object).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With