They are both used as a generic method of calling functions, member functions and generally anything that is callable. From cppreference the only real difference I see is that in std::invoke the function parameters (however many they are) are forwarded to the function, whereas in std::apply the parameters are passed as a tuple. Is this really the only difference? Why would they create a separate function just to handle tuples?
Is this really the only difference? Why would they create a separate function just to handle tuples?
Because you really need both options, since they do different things. Consider:
int f(int, int);
int g(tuple<int, int>);
tuple<int, int> tup(1, 2);
invoke(f, 1, 2); // calls f(1, 2)
invoke(g, tup); // calls g(tup)
apply(f, tup); // also calls f(1, 2)
Consider especially the difference between invoke(g, tup), which does not unpack the tuple, and apply(f, tup), which does. You sometimes need both, that needs to be expressed somehow.
You're right that generally these are very closely related operations. Indeed, Matt Calabrese is writing a library named Argot that combines both operations and you differentiate them not by the function you call but rather by how you decorate the arguments:
call(f, 1, 2); // f(1,2)
call(g, tup); // g(tup)
call(f, unpack(tup)); // f(1, 2), similar to python's f(*tup)
You use std::apply because:
1: Implementing apply, even if you have access to std::invoke is a big pain. Turning a tuple into a parameter pack is not a trivial operation. apply's implementation would look something like this (from cppref):
namespace detail {
template <class F, class Tuple, std::size_t... I>
constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>)
{
return std::invoke(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...);
}
} // namespace detail
template <class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t)
{
return detail::apply_impl(
std::forward<F>(f), std::forward<Tuple>(t),
std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
}
Sure, it's not the hardest code in the world to write, but it's not exactly trivial either. Especially if you don't the index_sequence metaprogramming trick.
2: Because calling a function by unpacking the elements of a tuple is rather useful. The basic operation it exists to support is the ability to package up a set of arguments, pass that set around, and then call a function with those parameters. We already technically have the ability to do that with a single parameter (by passing the value around), but through apply, you gain the ability to do it with multiple parameters.
It also allows you to do metaprogramming tricks, like meta-programmatically doing marshalling between languages. You register a function with such a system, which is given the function's signature (and the function itself). That signature is used to marshal the data through metaprogramming.
When the other language calls your function, the metaprogram-generated function walks the list of parameter types and extracts value(s) from the other language based on those types. What does it extract them into? Some kind of data structure that holds the values. And since metaprogramming cannot (easily) build a struct/class, you instead build a tuple (indeed, supporting metaprogramming like this is 80% of why tuple exists).
Once the tuple<Params> is built, you use std::apply to call the function. You can't really do that with invoke.
3: You don't want to make everyone stick parameters into a tuple just to be able to perform the equivalent of invoke.
4: You need to establish the difference between invokeing a function that takes a tuple, and applying to unpack the tuple. After all, if you're writing a template function that performs invoke on parameters the user specifies, it'd be terrible if the user just so happened to provide a single tuple as an argument and your invoke function unpacked it.
You could use other means to differentiate the cases, but having different functions is an adequate solution for the simple case. If you were writing a more generalized apply-style function, where you want to be able to unpack tuples in addition to passing other arguments or unpack multiple tuples into the argument lists (or a combination of these), you would want to have a special super_invoke that could handle that.
But invoke is a simple function for simple needs. The same goes for apply.
Related
In C++17 suppose I have a function-like object passed as a parameter to some template:
template<typename F>
void g(F f) {
auto x = f(/*...*/);
}
There are lots of different types F could be, such as a function pointer, a std::function, a lambda expression, and in fact any class type that implements operator().
Is there any way to get the function-like objects arity and type of its parameters and the type of its return type?
I mean, ultimately F could be a class that overloads operator() with multiple different member functions, each with different arities, parameter types and return types - so there isn't a fully-general answer (unless there is some way to iterate that overload set, which I don't think there is).
But for the typical case where a function call expression involving f results in a single overload, is there a solution?
(also if there is any progress in C++20, worth mentioning too)
C++17's adds deduction guides for std::function, which we can use to do the deduce the function signature of non-overloaded function-like objects:
template <typename R, typename... Args>
constexpr auto do_something_with_the_signature(std::function<R(Args...)>) {
// Assuming that you only care about the return type.
// Otherwise, you may want some kind of wrapper to extract the signature to
// avoid runtime cost
}
...
using some_type_computation =
decltype(do_something_with_the_signature(std::function(f)));
If you only wanted the return type, you could just use:
using result_type = typename decltype(std::function(f))::result_type;
If you want to avoid std::function altogether because of the compile-time costs, you can implement your own version of the deduction guides for your own type (possibly as general as a function_traits type trait). A sketch of how you might implement the deduction guides yourself can be seen in my answer here: https://stackoverflow.com/a/66038056/1896169
I have a custom logger that uses a logger->logf(format, ...) style varargs method for logging. I have object handles that are wrappers around pointers. I have a special format specifier to print the objects ( with a toString() method like in Java)
The "handles" are not "trivially copyable" as they can be constructed from a number of input types, and have converter-cast operators that return the pointer to the contained object type. ( similar to ComPtr<> )
IN windows C++ I can just pass the handle in and the varags method sees the pointer. GCC considers this an error now. The handle is "sizeof(void *)"
Is there a way to get GCC to allow this on a varags method?
Is there a way to specify a special operator xx () method to be passed into a varargs method?
I have a rather large library with a lot of log lines in it and redoing all of them with operator + or operator << would be an intense chore.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Well if does look like the Variadic template is what I need to use but I have yet to figure out how to make it simple an elegant.
The essence of an algorithm would be
place object or buffer on stack (ideally based on the number of arguments)
add all the arguments to the object.
on the last argument add it to the object, as well and process the arguments.
The "recursive" nature of a variadic template makes a nice way to do this a bit to figure out.
#
Ok I bit the bullet and rewrote the formatter part to use variadic templates. It did take 3 days. Basically it involves having an "Arg" class that has a union of all the primitive types and a "type" field set by the constructor overload for each type.
Then a variadic template to "load a list" of args which is passed to the formatters equivalent of "vsprintf". Great as there is enough information to be runtime type safe. The quastion now is HOW much code bloat is there with the template expansion. As all they do is cast and the "Arg" is a fixed size and it's constructor just loads two fields, type and value. Will GCC and MSC nicely optimize all of it out so there aren't 2 ^ maxArgs full expansions of the variadic templates.
template <typename... Args>
int writef(const wchar_t *fmt, ...) {
FormatfArglist<sizeof...(Args)> arglist;
FormatfArgBase::addArgs(arglist.args(), args...);
return(vwritef(fmt, arglist));
}
template <typename First, typename... Rest>
static void FormatfArgBase::addArgs(Arg *arglist,
const First &first, const Rest &... rest) {
setArg(arglist,Arg(first));
if(sizeof... (Rest) > 0) {
addArgs(++arglist, rest...); // recursive call using pack expansion syntax
}
}
Seems as the C++ guys pile on restrictions on the old C ellipsis one really has to use Variadic templates to get full functionality.
So I bit the bullet and rewrote the formatter part to use variadic templates. It did take 3 days. Basically it involves having an "Arg" class that has a union of all the primitive types and a "type" field set by the constructor overload for each type.
Then a variadic template to "load a list" of args which is passed to the formatters equivalent of "vsprintf". Great as there is enough information to be runtime type safe. The question now is HOW much code bloat is there with the template expansion. As all they do is cast and the "Arg" is a fixed size and it's constructor just loads two fields, type and value. Will GCC and MSC nicely optimize all of it out so there aren't 2 ^ maxArgs full expansions of the variadic templates?
// This is in a "TextWriter" class
template <typename... Args>
int writef(const wchar_t *fmt, ...) {
FormatfArglist<sizeof...(Args)> arglist;
FormatfArgBase::addArgs(arglist.args(), args...);
return(vwritef(fmt, arglist));
}
template <typename First, typename... Rest>
static void FormatfArgBase::addArgs(Arg *arglist,
const First &first, const Rest &... rest) {
setArg(arglist,Arg(first));
if(sizeof... (Rest) > 0) {
addArgs(++arglist, rest...); // recursive call using pack expansion syntax
}
}
I am not sure why it works with Microsoft compiler. The standard clearly indicates, that
Only arithmetic, enumeration, pointer, pointer to member, and class
type arguments are allowed.
(http://en.cppreference.com/w/cpp/language/variadic_arguments).
For your particular case, I suggest you use variadic template function as an intermediate step to convert those values to pointers, and than call your Log function (which I imagine can't be template itself).
I had a (lambda) function and a lot of functors passed as variadic argument pack into a third function. The signature looks like
template<typename F, typename... G>
ret_t call(F&& func, G&&... getters);
and F shall have as many as argument as the number of getters given.
Now I need to call func with the return value of getter called against a hard-coded (constexpr) constant determined otherwise. So untemplated code might look like
{
return func(getters_1(0), getters_2(0), getters_3(0) /* , ... */);
}
Of course I want to automate the process with template metaprogramming.
I want to avoid a temporary array or whatever intermediate container. (This is not aimed to that generic, I know the return type of getters.) I want it to be passed to the function as directly as possible so as to enable optimization and avoid waste of memory.
I could have wrapped F with many levels of closure of lambda, each wraps one parameter to it, and hope the best from compiler, but anyways I'm asking for better and clearer ways to do it.
If I understood you correctly you want something like this:
template<typename F, typename... G>
ret_t call(F&& func, G&&... getters) {
return std::forward<F>(func)(std::forward<G>(getters)(0)...);
}
There are a lot of examples on the web of using STL to pass in functions or function objects as parameters, for example in std::count .
How do I write my own functions that take such arguments?
As a simple example, say my class is:
struct Foo{
int val=0;
int methodinc()const{return val+1};
}
I would like to define a function funcall like:
int funcall (foo arg, function f)
{return f(arg); }
where the declaration “function” is what I am not sure of, among other things. The term “funcall” comes from Lisp, where (funcall f a b c) just applies f to the arguments a b c.
Then something like this should work:
Foo ff;
funcall(ff,Foo::methodinc); // should return 1
funcall(ff, [](Foo x) {return x.val+1;}) // should return 1
What are simple ways to accomplish this?
I am writing these as debugging helpers, the “funcall” would be used as part of the implementation of my own like my own data structure’s analogs of count, remove-if, transform and other like STL functions that take function arguments. But I do not want to write complicated template expressions to define my code.
The initial answers to this question suggest that the whole notion of declaring and using function arguments is a bit obscure, at least to me. Perhaps before addressing funcall, an even easier task might be just to pass a functional argument to another function, not use it. For example, in C++, to count a vector v I have to write
std::count(v.begin, v.end(), [](int j){return j>3})
How can one write a count that always counts the whole vector, so that:
mycount(v,[](int j){return j>3})
is the same as above? And could this "mycount" work for member function pointers instead of lambdas?
This question is basically the same as the "funcall" question but without the requirement actually to call the function object that is passed.
Typically a function template suits this sort of need for flexibility best:
template <typename F, typename T>
auto funcall(T && t, F f) -> decltype(f(std::forward<T>(t))
{
return f(std::forward<T>(t));
}
Instead of the trailing return type and decltype you can also use the result_of trait:
template <typename F, typename T>
typename std::result_of<F(T&&)>::type funcall(T && t, F f)
{
return f(std::forward<T>(t));
}
Or, in C++14, you can just say decltype(auto) funcall(T && t, F f) with no trailing return type, and it'll be deduced automatically.
The main reason for making F a deduced template argument rather than a fixed type (such as std::function<R(T)> is to allow you to call funcall directly with lambdas and bind/mem_fn expressions, which have unknowable types. Passing those directly allows efficient inlining opportunities, whereas creating of an std::function object is rather expensive by comparison.
C++ is an extraordinarily powerful and complex language. In it you can do anything you can do in Lisp, including implementing Lisp yourself. The problem is that to get there you will have to learn rather a lot about the language and what it can do. Using functions as objects is unfortunately one of the most complicated parts of C++.
There are multiple ways to solve your problem. The #Kerrek answer is an excellent one, but clearly beyond what you're ready for. The code provided in your edit is for a lambda, which will not necessarily make things simpler.
At its heart, function objects in C++ are just pointers. They look like this.
typedef int (*func)(int a, char b);
int f(int aa, char bb) {
return aa + bb;
}
int main(void) {
func fv = f;
int ret = fv(10, ' ');
printf ("ret=%d", ret);
return 0;
}
Here func is a type representing a function call, f is the actual function and fv is a functional call variable.
From this structure all else is built. With templates the compiler does the type matching and with lambdas you avoid having to think up nmes. Underneath it all, C/C++ functions are just pointers.
So the answer is that you can write your own functions that take functions as arguments when you know that those arguments are simply pointers to functions of a suitable type, declared as shown above.
I am playing around with the c++11 functional features. One thing I find odd is that the type of a lambda function is actually NOT a function<> type. What's more, lambda's do not seem to play really well with the type-inferencing mechanism.
Attached is a small example in which I tested flipping the two arguments of a function for adding two integers. (The compiler I used was gcc 4.6.2 under MinGW.) In the example, the type for addInt_f has been explicitly defined using function<> while addInt_l is a lambda whose type is type-inferenced with auto.
When I compiled the code, the flip function can accept the explicitly type-defined version of addInt but not the lambda version, giving an error saying that,
testCppBind.cpp:15:27: error: no matching function for call to 'flip(<lambda(int, int)>&)'
The next few lines show that the lambda version (as well as a 'raw' version) can be accepted if it's explicitly cast to the appropriate function<> type.
So my questions are:
Why is it that a lambda function does not have a function<> type in the first place? In the small example, why does not addInt_l have function<int (int,int)> as the type instead of having a different, lambda type? From the perspective of functional programming, what's the difference between a function/functional object and a lambda?
If there is a fundamental reason that these two have to be different. I heard that lambda's can be converted to function<> but they are different. Is this a design issue/defect of C++11, an implementation issue or is there a benefit in distinguishing the two as the way it is? It seems that the type-signature of addInt_l alone has provided enough information about the parameter and return types of the function.
Is there a way to write the lambda so that the above mentioned explicit type-casting can be avoided?
Thanks in advance.
//-- testCppBind.cpp --
#include <functional>
using namespace std;
using namespace std::placeholders;
template <typename T1,typename T2, typename T3>
function<T3 (T2, T1)> flip(function<T3 (T1, T2)> f) { return bind(f,_2,_1);}
function<int (int,int)> addInt_f = [](int a,int b) -> int { return a + b;};
auto addInt_l = [](int a,int b) -> int { return a + b;};
int addInt0(int a, int b) { return a+b;}
int main() {
auto ff = flip(addInt_f); //ok
auto ff1 = flip(addInt_l); //not ok
auto ff2 = flip((function<int (int,int)>)addInt_l); //ok
auto ff3 = flip((function<int (int,int)>)addInt0); //ok
return 0;
}
std::function is a tool useful to store any kind of callable object regardless of its type. In order to do this it needs to employ some type erasure technique, and that involves some overhead.
Any callable can be implicitly converted to a std::function, and that's why it usually works seamlessly.
I'll repeat to make sure it becomes clear: std::function is not something just for lambdas or function pointers: it's for any kind of callable. That includes things like struct some_callable { void operator()() {} };, for example. That is a simple one, but it could be something like this instead:
struct some_polymorphic_callable {
template <typename T>
void operator()(T);
};
A lambda is just yet another callable object, similar to instances of the some_callable object above. It can be stored in a std::function because it's callable, but it doesn't have the type erasure overhead of std::function.
And the committee plans to make lambdas polymorphic in the future, i.e., lambdas that look like some_polymorphic_callable above. Which std::function type would such a lambda be?
Now... Template parameter deduction, or implicit conversions. Pick one. That's a rule of C++ templates.
To pass a lambda as a std::function argument, it needs to be implicitly converted. Taking a std::function argument means that you're choosing implicit conversions over type deduction. But your function template needs the signature to be deduced or provided explicitly.
The solution? Don't restrict your callers to std::function. Accept any kind of callable.
template <typename Fun>
auto flip(Fun&& f) -> decltype(std::bind(std::forward<Fun>(f),_2,_1))
{ return std::bind(std::forward<Fun>(f),_2,_1); }
You may now be thinking why do we need std::function then. std::function provides type erasure for callables with a known signature. That essentially makes it useful to store type-erased callables and to write virtual interfaces.
Because function<> employs type erasure. This allows several different function-like types to be stored in a function<>, but incurs a small runtime penalty. Type erasure hides the actual type (your specific lambda) behind a virtual function interface.
There is a benefit to this: one of the C++ design "axioms" is to never add overhead unless it is really needed. Using this setup, you do not have any overhead when using type inference (use auto or pass as a template parameter), but you still have all the flexibility to interface with non-template code through function<>. Also note that function<> is not a language construct, but a component of the standard library that can be implemented using simple language features.
No, but you can write the function to just take the type of the function (language construct) instead of the specifics of the function<> (library construct). Of course, that makes it a lot harder to actually write down the return type, since it does not directly give you the parameter types. However, using some meta-programming a la Boost.FunctionTypes you can deduce these from the function you pass in. There are some cases where this is not possible though, for example with functors that have a templated operator().