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:
- Why do I get the error? [compiler bug or some arcane C++ rule?]
- How can I achieve the same effect without first explicitly constructing
F?
(Currently, I have solved the problem by introducing another template parameter on partition3 and declaring P as that template type.)
cmp()isn’t actually astd::functionat 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: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 ofstd::functionbecomes 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.