Reputation: 24574
I have a function declared as follows; its exact working is not relevant for this.
template<typename T>
std::pair<int, int>
partition3(T *pT, const int N, const T &Kq, const int w,
std::function<int(const T&, const T&, int)> P);
At the call site I attempt to do the following:
bool partition3_test()
{
struct cmp
{
int operator()(int x, int y, int) const
{ return x-y; }
};
int V1[11] = { 3, 7, 1, 7, 7, 8, 10, 2, 16, 4, 3 },
V2[11] = { 3, 6, 1, 6, 6, 8, 10, 2, 16, 4, 3 };
std::function<int(const int&, const int&, int)> F = cmp();
std::pair<int, int>
p1 = partition3(V1, 11, 7, 0, cmp()),
p2 = partition3(V2, 11, 7, 0, cmp());
return false;
}
For the two calls of partition3
the compiler (MSVC 2010) complains that it could not deduce template argument for the last parameter. If I replace cmp()
with F
, the code compiles and works fine.
I have two questions:
F
?(Currently, I have solved the problem by introducing another template parameter on partition3
and declaring P
as that template type.)
Upvotes: 1
Views: 301
Reputation: 283793
cmp()
isn't actually a std::function
at all. The fact that the copy-initialization works may be confusing the issue, but that uses a converting constructor which must be using some sort of wrapper object, and I'm surprised that it works against a temporary functor object (ah, checking the standard it apparently make a copy of the functor).
On top of that, the function arguments don't match (pass-by-value and pass-by-const-reference are source-compatible, but not runtime-call-compatible), which again requires an adaptor.
The best solution is to make the template function more generic, so that it also works with raw function pointers and arbitrary functor objects, not just std::function
:
template<typename T, typename Functor>
std::pair<int, int> partition3(T *pT, const int N, const T &Kq, const int w,
const Functor& P);
If for some reason you really wanted to use std::function
(you need the virtual dispatch, for instance), you can. The error, quite contrary to what Nawaz wrote, is that this is a deducible context, but more than one type fits (this is where the adaptor/wrapper nature of std::function
becomes important, because the type doesn't have to exactly match the parameter, it just has to be compatible. std::function<int(const long&, const long&, int)>
would match just as well.)
Use instead a non-deducible context, that way the compiler won't even try to use the functor for deduction of T
.
template<typename T, typename Functor>
std::pair<int, int> partition3(T *pT, const int N, const T &Kq, const int w,
std::function<std::identity<const T>::type&, std::identity<const T>::type&, int> P);
Upvotes: 4