In C++ how do we call everything with a valid X(Args...) syntax that execute a function? - c++

In C++, there is a Callable concept as well as the std::is_function type traits. I was wondering how the standard calls X, when the exact expression
X(Args...)
is valid and corresponds to a call (excluding constructors and C macros). For now, I can think of the following that fit in that category:
functions: R(Args...) (with optional const, volatile, &, && qualifiers)
function pointers: R(*)(Args...)
function references: R(&)(Args...)
functors (struct/class with overloaded operator())
lambda
My questions:
How does the standard call X? (eg.: not a is_function type because if X is a function pointer, X(Args...) is valid but is_function is false)
Did I forgot something in my list?

Your question seems a bit confused. std::is_function only identifies actual function types. It doesn't even include pointers to functions. The FunctionObject concept includes any object type that you can apply the function call operator to. This basically covers your list.
The Callable concept includes FunctionObjects, but it includes other things. Callable adds member pointers (both data and functions) to the rest of the FunctionObject family.
The INVOKE feature of C++ is what gets applied to all Callable objects. INVOKE is not actually a function in C++; it's simply the standard's name for the algorithm for calling Callable objects with an argument list (C++17 corrects this absurd overseight, giving us std::invoke). Section 20.9.2 of the standard covers exactly how this algorithm is implemented.
The general gist is what you would expect. If the callable is a pointer-to-member-data, then you take the first argument, and apply that to the pointer-to-member-data (dereferencing that argument if it isn't a pointer). Same goes for pointer-to-member-functions, only you pass the rest of the arguments as parameters.
For FunctionObject types, you just use () to call it, passing it the arguments.

Related

What's the difference between C++23's optional::transform and optional::and_then?

C++23 adds some "monadic-style" functionality regarding optionals, as methods of optional<T>:
optional<T>::and_then() (and ignoring qualifiers of this):
template<class F> constexpr auto and_then(F&& f);
Returns
the result of invocation of f on the contained value if it exists.
Otherwise, returns an empty value of the return type.
optional<T>::transform() (and ignoring qualifiers of this):
template<class F> constexpr auto transform(F&& f);
Returns an std::optional that contains the result of invocation of f on the contained value if *this contains a value. Otherwise, returns an empty std::optional of such type.
So, aren't these two functions doing the same thing?
Suppose you have an optional<T1> value.
transform() lets you pass your optional to functions like T2 foo(T1 x);
and_then() lets you pass your optional to functions like optional<T2> bar(T1 x);
... and get an optional<T2> at the end. So, transform() will "re-box" the function's output into an optional, while and_then() will expect the function to return a boxed value on its own.
See also this question.
and_then is monadic bind aka flatmap aka >>= and transform is functorial map.
One can express map in terms of bind generically, but not the other way around, because a functor is not necessarily a monad. Of course the particular monad of std::optional can be opened at any time, so both functions are expressible in terms of ordinary pre-C++23 std::optional API. Thus the question why the C++ standard defines both functions is no better than the question why it defines any of the two. Perhaps the Standard wishes to give the programmer a standard functorial interface and a standard monadic interface independently. Either interface is useful and important on its own right.
and_then only takes functions of type T -> std::optional<U> (whereas transform is free to take functions returning any type).
If you just transform with such a function you will get a std::optional<std::optional<U>>.
and_then just then flattens the std::optional<std::optional<U>> into an std::optional<U>.
That's all monads are: transform composed with a type level flatten. Think range<range<U>> and future<future<U>>.

What is the advantage of using boost::bind?

The definition and application of boost::bind are clearly outlined in the boost website, yet I hardly could find what is the benefit of using it over using a normal function call? Or to put it simply in which scenarios it might come in handy?
Sometimes you have a set of arguments that you are going to pass to the function, but you wish to call the function later without needing to pass the arguments that are already known. One reason to need this may be because the call may need to conform to an interface that doesn't allow those arguments. This is typical in the (functor style) "callback" idiom.
That situation can be solved by defining a class that stores the arguments as members, and defines function call operator overload that delegates to the original function and passes the arguments stored as members.
boost::bind is a structured way to represent such "argument binding" without needing to define the class yourself. The standard library used to have std::bind1st and std::bind2nd which were more limited, less generic forms of bind.
boost::bind is rarely needed anymore since it was introduced to the standard library as std::bind in C++11, and furthermore lambdas were introduced in C++11 and improved in C++14 and they have largely obsoleted bind.
bind provides a way to take a function or a function object with a certain arity and transform it to another function with lesser arity by precisely binding one or more arguments. And you can do it in place.
bind and functions don't have a good comparison.
bind is more comparable to simple lambdas that call a function and fix certain parameters in their implementation.
The big difference between boost::bind and a modern lambda is that the bind object has a certain degree of instrospection associated with it that the lambda doesn't have.
For example you could in principle recover the original function and reconstruct what is the argument bound.
In a lambda everything is private, even the simplest implementation.
In other words, the result of boost::bind is an "expression" and the type has well defined pattern (e.g. boost::bind_t<...> or something, and that can be matched in a template function argument).
Lambdas instead are each their own unknowable sui generis type.
Admittedly, few people maybe interested in the difference, but it is there and I played with it once or twice to implement a symbolic system (for derivatives).
I can't say the same about std::bind because the object returned is unspecified by the standard and it could be more difficult to reconstruct the full bind "expression".

How to get a meaningful function signature from anything callable

Consider such a beast:
template<typename Func>
void register_function(Func func) {
// type-erase Func and pass it on to some other function
}
Assume that this can be passed anything callable.
I know how to get at the function's signature if Func is a plain function type. Given that func could be a plain function, a std::function<F>, or a function object (a std::bind() expression), how can I get at the function's arguments?
Note:
in this case, the functions only ever have either zero, one, or two arguments
if it's a function object, it's the result of std::bind()
the signature is needed in order to get at the argument's types, which need to be usable in the type-erased thing passed on
this is strictly C++03 (embedded platform), so no variable template arguments etc.
Impossible. A function object can have overloaded or templated operator(). Thus the idea of it having "a signature" simply doesn't apply, because it can have an unbounded number of signatures.
If you restrict it to only having one signature, then you can take the address of operator() and then get the arguments from the member function pointer type using regular template specialization.
If you know at runtime the signature of some called (plain) function, you could use (on Linux notably) the libffi to call it.
If you don't even know at runtime the signature of the function to call, it is impossible, since in general the ABI conventions will dictate different ways of passing function arguments according to their type.
For instance, the x86-64 ABI (followed on most Linux 64 bits x86-64 systems) requires that floating point values and integral values are passed in different set of registers.
See for example the x86 calling conventions wikipage.

What are the rules for function pointers and member function pointers to Standard functions?

What are the existing rules for taking function pointers or member function pointers to Standard functions? For example, something like
auto p = &std::string::size;
Is this legal? Would it be more or less legal if I explicitly requested the correct type, so it would function even if there was an additional implementation-added overload of std::string::size?
Using the "correct" type doesn't make things better: Except for the virtual functions all functions in the standard C++ library can have additional arguments as long as these are defaulted. Since the functions can also be declared with additional overloads (again with the exception of the virtual function), you can end up trying to assign an overload set a variable. Thus, the code isn't portable and there is no way to make it portable by using some sort of cast or some signature instead of auto.
The relevant quote is 17.6.5.5 [member.functions] paragraph 1:
An implementation may declare additional non-virtual member function signatures within a class:
--- by adding arguments with default values to a member function signature;
— by replacing a member function signature with default values by two or more member function signatures with equivalent behavior; and
— by adding a member function signature for a member function name.
I don't see a similar permission for non-member functions, though. Not sure where the permission to mess with these is hiding but I'm relatively sure that there are some weasel words for these as well. Looking further, it seems non-member functions are more constrained according to 17.6.5.4 [global.functions] paragraph 3:
An implementation shall not declare a global or non-member function signature with additional default arguments.
This would imply that you can take the address of the non-member functions, at least, when specifying the desired signature.

boost::bind accessors?

Suppose I have the following code:
int f(int, int);
int main()
{
SomeFunc(boost::bind(f, 1, 2));
}
From the SomeFunc() function, is it possible to access the arguments held by the bound type? Something like this (pseudo code):
// Obvious syntax issues...
void SomeFunc(boost::bind& functor)
{
if(functor.function == &f)
{
if(functor.argument1 == 1)
DoSomething();
}
}
Can I pull this information out of the boost::bind type?
boost::bind is a templated function, not a type. The real type returned by that function is some kind of functor of an unspecified type. As a matter of fact, it probably returns many different unspecified types depending on what the arguments to the boost::bind function are.
As the type is unspecified and the library only states that is CopyConstructible, that implements operator() with the appropriate number and type of arguments (one for each placeholder, types deduced from the bound method/function) and that it offers an inner type result_type that is the same as the return type of that operator().
The interface of those unspecified classes is, well, unspecified. It will probably not offer accessors to the arguments, and even if it does, and you get inside knowledge from studying the internals of the library, you risk having your code break with upgrades to the library (the implementor is free to change the type and all the interface that is not publicly documented).
The whole library is built around the fact that you do not really care about what the arguments are or even if any argument is defined or only placeholders are used, you only care that the resulting object will be callable with a given interface.
So no, you cannot.
The real question is why would you want to do that?
I suspect you can't but the fact that you are trying is a bit worrying.
No, you cannot do that with boost::bind.
boost::bind just generates a sort of functor object where all details are hidden. Than you construct boost::function or boost::signal with it and the only thing you can do: execute. You even cannot compare boost::function objects.
Anyway, it is not clear that the problem you are solving. Such approach looks awkward to me. Are you sure you really need that?