Why can't `std::async` pick the correct overload? - c++

Please consider the following example:
#include <iostream>
#include <future>
std::size_t calc_something(std::size_t lim_)
{
std::size_t result = lim_ * 10;
return result;
}
void calc_something(std::size_t lim_, std::promise<std::size_t> &promise_)
{
std::size_t result = lim_ * 10;
promise_.set_value(result);
}
void async_calc()
{
std::future<std::size_t> async_calc = std::async(calc_something, 5);
std::cout<< "async_calc = " << async_calc.get() <<std::endl;
}
I am still new to multi-threading, but why -on earth- can't std::async pick the correct overload? The second overload uses a reference to an std::promise object.
I've looked at this question here but it doesn't explain why. Also, I do not get an ambiguity error.
The error I get is:
error: no matching function for call to 'async' std::future<std::size_t> async_calc = std::async(calc_something, 5);

Overload resolution happens based on types of arguments specified at the call site. When you're calling std::async, you're not calling calc_something but passing a pointer to the function to std::async. There are no calc_something call arguments and no way to resolve which of the two overloads' address to pass to std::async.
The compiler cannot use the subsequent arguments of std::async to resolve the overload. From the compiler's perspective, all std::async arguments are unrelated and nothing implies they will be used to invoke calc_something. In fact, you can call std::async with arguments of types different from those calc_something accepts, and it will work because they will get converted when calc_something is invoked.
In order to resolve this ambiguity, you must explicitly cast the pointer to calc_something to the exact type of the function pointer, matching one of the overloads.
std::async((std::size_t (*)(std::size_t))calc_something, 5);

Overload sets cannot be sent as parameter as is, it must be converted to a function pointer first, or must be lifted into an object.
Overload sets must be converted since only the name of the function denote the complete set of functions, but you must send only one of those. How the compiler chooses the right one depends on the arguments you sent to it. Calling it provides the type of the parameters, but converting to a function pointer also provide the compiler with enough information about which overload must be sent.
Converting to a function pointer is usually the easy way:
auto function = static_cast<std::size_t(*)(std::size_t)>(calc_something);
std::future<std::size_t> async_calc = std::async(function, 5);
Lifting is done using a lambda:
std::future<std::size_t> async_calc = std::async([](auto lim) { return calc_something(lim); }, 5);
Lifting here is possible since you call the overload set, so there is a parameter the compiler can choose.
It just cannot delay that decision for overload sets, but for lambda and template function it can.

std::async() is a function template and you pass calc_something as an argument to it. However, there are two functions called calc_something due to overloading. The calc_something() overload has to be selected before the template deduction of std::async()'s arguments takes place.
std::future<std::size_t> async_calc = std::async(calc_something, 5);
In the code above, which overload will be passed to std::async()?
std::size_t calc_something(std::size_t);
void calc_something(std::size_t, std::promise<std::size_t> &);
You have to specify:
std::async(static_cast<std::size_t(*)(std::size_t)>(calc_something), 5);

Related

Get pointer to overloaded function that would be called

Please refer to the following:
struct functorOverloaded
{
void operator()(const int& in_, ...) const {}
void operator()(short in_) {}
};
// helper to resolve pointer to overloaded function
template <typename C, typename... OverloadArgs>
auto resolve_overload(
std::invoke_result_t<C, OverloadArgs...> (C::* func)(OverloadArgs..., ...) const
)
{ return func; };
int main(int argc, char **argv)
{
using C = const functorOverloaded;
// works with exact function type
using myT = decltype(resolve_overload<C, const int&>(&C::operator()));
// can call with something convertible to const int&
static_assert(std::is_invocable_v<C,int>, "!!!");
// how to get the pointer to the overload that would be called when passed int (or double)?
// the next line doesn't compile (error C2672: 'resolve_overload': no matching overloaded function found)
using myT2 = decltype(resolve_overload<C, int>(&C::operator()));
return 0;
}
The above code allows retrieving a pointer to a specific overload of a function (operator() in this case), see here. One must know the exact argument type (const int&) in this case to get the pointer, even though i can just call the specific overload with a plain int, or even double. Is it possible to get a pointer to the overload that would be called with the specific argument (assuming the call is resolvable / not ambiguous)?
Edit: adding context:
I am writing a invocable_traits library for introspecting a callable. E.g., given a Callable, it will tell you the return type, arity and argument types, amongst some other properties. To support functors (including lambdas) with overloaded (or templated) operator(), the API of invocable_traits allows specifying call arguments to disambiguate which overload is to be used (or to instantiate the template). However, one must know the exact argument type (const int& in the example above), simply specifying int won't do in that case as there is no function with signature R operator()(int). Ideally, I'd like to allow discovering the signature of the exact overload/instantiation that gets called given the provided input argument types, ideally even taking into account any implicit conversions that are applied. Is this possible?
There is no way to get the function of an overload-set which would be called with the given arguments, unless you already know its signature.
And if you know, what's the point?
The problem is that for any given arguments, taking into account implicit conversions, references, cv-qualifiers, noexcept, old-style vararg, default arguments, and maybe also literal 0 being a null pointer constant, there are an infinite number of function-signatures which would match. And there is currently no facility for "just" listing all candidates.

Function which converts from from a_func(A a_in) to b_func(B b_in) (c++)

I have a class of function (call it AFunc) which takes a parameter of type A, and a class of function (call it BFunc) which takes a parallel parameter of type B (i.e. there is a straightforward conversion from objects of type A to those of type B).
I need to write a function like the following:
using Afunc = AReturnType(*)(A);
using BFunc = BReturnType(*)(B);
BFunc convertFunction(AFunc a_func_in)
{
BReturnType(*b_func_out) =
[&](B b_in) {
A a_in = A(b_in);
AReturnType a_out = a_func_in(a_in);
return BReturnType(a_out);
};
return b_func_out;
}
That is, a function which takes a function compatible with A types and returns a function compatible with B types.
My first thought was to define a function within the conversion function, but I quickly discovered that local functions are not supported in c++. My next thought was to use a lambda expression as above, but I have since learned that lambda functions can only be decayed to function pointers if they don't capture any references, however in this case the lambda needs to be aware of the AFunc parameter provided to the wider conversion function.
This is where I've run out of ideas. Is there any other way of doing this?
The problem is that having a function pointer is stronger than simply having a callable object. The latter could be a function pointer, but it could also be a closure or a functor, both of which carry state. A function pointer is just that: a pointer to a function. No state, no special tricks. Just one chunk of code that can be executed on demand.
So, at least, there's no way to pass an AFunc at runtime and get a BFunc, the way you've defined everything, because that would involve generating new functions in the code itself at runtime, which C++ doesn't allow.
However, if you know the AFunc you want to apply this too at compile-time, we can use templates to get the same result. A template is evaluated at compile-time and actually generates code, so we can use it to come up with functions which have genuine function pointers. In fact, we're not even going to write a conversion function; we're just going to write our BFunc and then template parameterize it.
template <AFunc f>
BReturnType bFunc(B b) {
return f(b);
}
Assuming the appropriate conversions exist, you can write something like BFunc b = bFunc<sampleAFunc>; and the compiler will generate the appropriate function (and corresponding pointer) for you.

How I can pass callable object to function as parameter

In c++ standard library almost all algo function takes a callable object as a argument. Now I want to try this thing with my program. I opened the the headers for function like find_if or search_n() but could not understand much about how these callable object parameters are handled and off course how argument is passed to them especially for lambda object ( can bind() be used for lambdas, I dont know)
Can any one explain me how this thing works. Thanks in advance
Just have a template parameter for the function-like type and take an argument of that type:
template <typename Function>
void foo(Function func) {
// Use func like so
func(10);
}
This is how the standard library algorithms do it. You could call it with a lambda like so:
foo([](int x) { std::cout << (x * 2) << std::endl; });
Of course, this requires that you specify in your documentation what kind of function you expect as the Function type (until we get (until we get Concepts). Should it be unary? Binary? What type arguments should it take? What should it return?
Alternatively, you can take a function of a specific type by using std::function:
int foo(std::function<int(char)> func) {
return func('a');
}
This time, foo will only take function-like objects that take a char argument and return an int. There is one downside to this method, however, which is that the compiler is unlikely to inline any lambdas you pass as func.
The most basic way to take a function as an argument is with a function pointer:
int foo(int (*func)(char)) {
return func('a');
}
However, this will only take function pointers (some lambdas can be converted to function pointers). It won't take functors or anything else of the sort.
All algorithm function must get some functions to test the algo like find_if have to know which predicate you want to test on the loop. All std lib works with template and you can pass your function test as callable object. Callable object are object that have overload operator(), with it, std lib will call your sent object with some parameter and get up a return value if necessary. You can find which parameters and return values that are needed on some site, specialy I always use http://www.cplusplus.com/ you can find many documentation on all std lib in reference menu.
Special exemple from you :
http://www.cplusplus.com/reference/algorithm/find_if/
find_if will take 2 iterators, one as first and an other as last, and a callable object that will take a object pointed by your iterator and return a bool.

Why does boost::bind store arguments of the type passed in rather than of the type expected by the function?

I recently ran into a bug in my code when using boost::bind.
From the boost::bind docs:
The arguments that bind takes are copied and held internally by the returned function object.
I had assumed that the type of the copy that was being held was based on the signature of the function. However, it is actually based on the type of the value passed in.
In my case an implicit conversion was happening to convert the type used in the bind expression to the type received by the function. I was expecting this conversion to happen at the site of the bind, however it happens when the resulting function object is used.
In retrospect I should have been able to figure this out from the fact that using boost::bind gives errors when types are not compatible only at the call site, not the bind site.
My question is:
Why does boost::bind work this way?
It seems to give worse compiler error messages
It seems to be less efficient when implicit conversion happens and there are multiple calls to the functor
But given how well Boost is designed I'm guessing there is a reason. Was it behavior inherited from std::bind1st/bind2nd? Is there a subtle reason why this would be hard/impossible to implement? Something else entirely?
To test that second theory I wrote up a little code snippet that seems to work, but there may well be features of bind I haven't accounted for since it's just a fragment:
namespace b = boost;
template<class R, class B1, class A1>
b::_bi::bind_t<R, R (*) (B1), typename b::_bi::list_av_1<B1>::type>
mybind(R (*f) (B1), A1 a1)
{
typedef R (*F) (B1);
typedef typename b::_bi::list_av_1<B1>::type list_type;
return b::_bi::bind_t<R, F, list_type> (f, list_type(B1(a1)));
}
struct Convertible
{
Convertible(int a) : b(a) {}
int b;
};
int foo(Convertible bar)
{
return 2+bar.b;
}
void mainFunc()
{
int x = 3;
b::function<int()> funcObj = mybind(foo, x);
printf("val: %d\n", funcObj());
}
Because the functor may support multiple overloads, which may give different behaviours. Even if this signature could be resolved when you knew all the arguments (and I don't know if Standard C++ can guarantee this facility) bind does not know all the arguments, and therefore it definitely cannot be provided. Therefore, bind does not possess the necessary information.
Edit: Just to clarify, consider
struct x {
void operator()(int, std::vector<float>);
void operator()(float, std::string);
};
int main() {
auto b = std::bind(x(), 1); // convert or not?
}
Even if you were to reflect on the struct and gain the knowledge of it's overloads, it's still undecidable as to whether you need to convert the 1 to a float or not.
There are different cases where you need the arguments to be processed at the call site.
The first such example is calling a member function, where you can either have the member called on a copy of the object (boost::bind( &std::vector<int>::push_back, myvector)) which most probably you don't want, or else you need to pass a pointer and the binder will dereference the pointer as needed (boost::bind( &std::vector<int>::push_back, &myvector )) --Note both options can make sense in different programs
Another important use case is passing an argument by reference to a function. bind will copy performing the equivalent to a pass-by-value call. The library offers the option of wrapping arguments through the helper functions ref and cref, both of which store a pointer to the actual object to be passed, and at the place of call they dereference the pointer (through an implicit conversion). If the conversion to the target type was performed at bind time, then this would be impossible to implement.
I think this is due to the fact that bind has to work with any callable entity, be it a function pointer, std::function<>, or your own functor struct with operator(). This makes bind generic on any type that can be called using (). I.e. Bind's implicit requirement on your functor is just that it can be used with ()
If bind was to store the function argument types, it would have to somehow infer them for any callable entity passed in as a type parameter. This would obviously not be as generic, since deducing parameter types of an operator() of a passed-in struct type is impossible without relying on the user to specify some kind of typedef (as an example). As a result the requirement on the functor (or concept) is no longer concrete/simple.
I am not entirely sure this is the reason, but it's one of the things that would be a problem.
EDIT: Another point as DeadMG mentions in another answer, overloads would create ambiguities even for standard function pointers, since the compiler would not be able to resolve the functor type. By storing the types you provide to bind and using (), this problem is also avoided.
A good example would binding "std::future"s to some ordinary function taking ordinary types:
Say I want to use an ordinary f(x,y) function in an incredibly asynchronous way. Namely, I want to call it like "f(X.get(), Y.get())". There's a good reason for this- I can just call that line and f's logic will run as soon as both inputs are available (I don't need separate lines of code for the join). To do this I need the following:
1) I need to support implicit conversions "std::future<T> -> T". This means std::future or my custom equivalent needs a cast operator:
operator T() { return get(); }
2) Next, I need to bind my generic function to hide all its parameters
// Hide the parameters
template<typename OUTPUT, typename... INPUTS>
std::function<OUTPUT()> BindVariadic(std::function<OUTPUT(INPUTS...)> f,
INPUTS&&... in)
{
std::function<OUTPUT()> stub = std::bind( f, std::forward<INPUTS>(in)...);
return stub;
}
With a std::bind that does the "std::function<T> -> T" conversion at call time, I only wait for all the input parameters to become available when I ACTUALLY CALL "stub()". If it did the conversion via operator T() at the bind, the logic would silently force the wait when I actually constructed "stub" instead of when I use it. That might be fatal if "stub()" cannot always run safely in the same thread I built it.
There are other use cases that also forced that design choice. This elaborate one for async processing is simply the one I'm personally familiar with.

Correct Way to Define a Predicate Function in C++

I'm trying to write predicate function for use with STL algorithms. I see that they are two ways to define a predicate:
(1) Use a simple function as below:
bool isEven(unsigned int i) { return (i % 2 == 0); }
std::find_if(itBegin, itEnd, isEven);
(2) Use the operator() function as below:
class checker {
public:
bool operator()(unsigned int i) { return (i % 2 == 0); }
};
std::find_if(itBegin, itEnd, checker);
I have more use for the second type as I usually would like to create a predicate object with some members in it and use them in the algorithm. When I add the same isEven function inside checker and use it as a predicate, I get an error:
3. Syntax which gives error:
class checker {
public:
bool isEven(unsigned int i)
{ return (i%2 == 0); }
};
checker c;
std::find_if(itBegin, itEnd, c.isEven);
Calling c.isEven gives an error during compilation saying undefined reference to some function. Can someone explain why 3. is giving error? Also, I would appreciate any pointers to read about predicate and iterator basics.
A pointer to a member function requires an instance to be called on, and you are passing only the member function pointer to std::find_if (actually your syntax is incorrect, so it doesn't work at all; the correct syntax is std::find_if(itBegin, itEnd, &checker::isEven) which then still doesn't work for the reasons I gave).
The find_if function expects to be able to call the function using a single parameter (the object to test), but it actually needs two to call a member function: the instance this pointer and the object to compare.
Overloading operator() allows you to pass both the instance and the function object at the same time, because they're now the same thing. With a member function pointer you must pass two pieces of information to a function that expects only one.
There is a way to do this using std::bind (which requires the <functional> header):
checker c;
std::find_if(itBegin, itEnd, std::bind(&checker::isEven, &c, std::placeholders::_1));
If your compiler doesn't support std::bind, you can also use boost::bind for this. Though there's no real advantage to doing this over just overloading operator().
To elaborate a bit more, std::find_if expects a function pointer matching the signature bool (*pred)(unsigned int) or something that behaves that way. It doesn't actually need to be a function pointer, because the type of the predicate is bound by the template. Anything that behaves like a bool (*pred)(unsigned int) is acceptable, which is why functors work: they can be called with a single parameter and return a bool.
As others have pointed out, the type of checker::isEven is bool (checker::*pred)(unsigned int) which doesn't behave like the original function pointer, because it needs an instance of checker to be called on.
A pointer to a member function can be conceptually considered as a regular function pointer that takes an additional argument, the this pointer (e.g. bool (*pred)(checker*, unsigned int)). You can actually generate a wrapper that can be called that way using std::mem_fn(&checker::isEven) (also from <functional>). That still doesn't help you, because now you have a function object that must be called with two parameters rather than only one, which std::find_if still doesn't like.
Using std::bind treats the pointer to a member function as if it was a function taking the this pointer as its first argument. The arguments passed to std::bind specify that the first argument should always be &c, and the second argument should bind to the first argument of the newly returned function object. This function object is a wrapper that can be called with one argument, and can therefore be used with std::find_if.
Although the return type of std::bind is unspecified, you can convert it to a std::function<bool(unsigned int)> (in this particular case) if you need to refer to the bound function object explicitly rather than passing it straight to another function like I did in my example.
I guess it's because the type of c.isEven() is,
bool (checker::*)(unsigned int) // member function of class
which may not be expected by find_if(). std::find_if should be expecting either a function pointer (bool (*)(unsigned int)) or a function object.
Edit: Another constraint: A non-static member function pointer must be called by the class object. In your case, even if you succeed to pass the member function then still find_if() will not have any information about any checker object; so it doesn't make sense to have find_if() overloaded for accepting a member function pointer argument.
Note: In general c.isEven is not the right way to pass member function pointer; it should be passed as, &checker::isEven.
checker::isEven is not a function; it is a member function. And you cannot call a non-static member function without a reference to a checker object. So you can't just use a member function in any old place that you could pass a function pointer. Member pointers have special syntax that requires more than just () to call.
That's why functors use operator(); this makes the object callable without having to use a member function pointer.
I prefer functors (function objects) because make your program more readable and, more importantly, expressing the intent clearly.
This is my favorite example:
template <typename N>
struct multiplies
{
N operator() (const N& x, const N& y) { return x * y; }
};
vector<int> nums{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Example accumulate with transparent operator functor
double result = accumulate(cbegin(nums), cend(nums), 1.1, multiplies<>());
Note: In recent years we've got a lambda expression support.
// Same example with lambda expression
double result = accumulate(cbegin(nums), cend(nums), 1.1,
[](double x, double y) { return x * y; });
The example given says you should use the call operator (operator()) whereas in your example you've called your function isEven. Try re-writing it as:
class checker {
public:
bool operator()(unsigned int i)
{ return (i%2 == 0); }
};