Reputation: 417
Given the two function templates below:
template <typename T>
void gorp(T*, std::function<void(T*)>)
{
}
template <typename T>
void klop(T*, std::function<void()>)
{
}
The function klop()
works as I expect, but gorp()
does not:
int x = 3;
//fails: candidate template ignored: could not match
//'function<void (type-parameter-0-0 *)>' against '(lambda at ...)
gorp( &x, [](int*){}); //1
//works
gorp<int>( &x, [](int*){}); //2
//fails: candidate template ignored: could not match
//'function<void (type-parameter-0-0 *)>' against 'void (^)(int *)'
gorp( &x, ^(int*){}); //3
//works
gorp<int>( &x, ^(int*){}); //4
//works
klop( &x, [](){}); //5
//works
klop( &x, ^(){}); //6
Lines 3,4,6 use clang blocks; lines 1,2,5 use lambdas.
Notice the calls to klop()
have no problem inferring T
, but I have to help out the calls to gorp()
.
I'm at a loss. Shouldn't it be doubly easy for gorp()
to figure out T
?
Upvotes: 0
Views: 120
Reputation: 120059
If you must have std::function
, you can inhibit type deduction for this argument:
template<typename T>
void gorp (T* t, std::function<void(std::type_identity_t<T*>)> func);
int x;
gorp(&x, [](int*){}); // works
However I would recommend
template <typename T, typename F>
void gorp(T* t, F&& f) requires(requires {f(t);})
{
f(t);
}
This accepts everything the previous version accepts, and more, and does so more efficiently without conversion to std::function
.
Upvotes: 2
Reputation: 249542
It won't infer the type T
because you're not passing a std::function
. The type inference doesn't work if a conversion is also required. This does work:
gorp(&x, std::function<void(int*)>([](int*) {}));
And so does this, using plain function pointers:
template <typename T>
void gorp(T*, void(*)(T*))
{
}
gorp(&x, +[](int*) {}); // + converts captureless lambda to function pointer
Or to support Clang "blocks":
template <typename T>
void gorp(T*, void(^)(T*))
{
}
And finally, to support all of the above with a single definition:
template <typename T, typename F>
void gorp(T*, F&& f)
{
}
This can be more efficient than a definition taking std::function
if the function is called many times, as std::function
does carry some overhead.
Upvotes: 1