So far, we have learned how the compiler can make our templated functions easier to use by automatically deducing the types used. The template code decides whether to accept a parameter as a value or a reference, and the compiler finds the type for us. But what do we do if we want to be agnostic regarding whether an argument is a value or a reference, and we want to work with it regardless?
An example would be std::invoke in C++17. std::invoke is a function that takes a function as the first argument, followed by a list of arguments, and calls the function with the arguments. For example:
void do_action(int, float, double); double d = 1.5; std::invoke(do_action, 1, 1.2f, d);
Similar examples would apply if you wanted to log before calling a function, or you wanted to execute the function in a different thread, such as std::async does.
Let's demystify the difference by using the following code:
struct PrintOnCopyOrMove { PrintOnCopyOrMove(std::string name) : _name...