Problem
I wish to make a function which accepts an arbitrary number of functor objects or more generally just callable objects (of different types) and applies them to an internal data structure. The function will be used with differing numbers of functors at different points in my code.
Rather than make different version to accept 1,2,3... etc and duplicate code I thought about using variadic templates.
I have found a solution which I will post below as an answer since I couldn't find anything on Google about specifically this and others might find it useful. But, please, if anyone has any better ideas post them. I have a feeling there should be a std way to do this?
Naive Attempt
I kind of knew this wouldn't work but my first attempt was
#include <iostream>
using namespace std;
struct FunctorA {
void operator() () {
cout << "FunctorA" << endl;
}
};
struct FunctorB {
void operator() () {
cout << "FunctorB" << endl;
}
};
template<typename... Fs>
void apply_functors(Fs... fs) {
fs()...; // will not work - can only expand packs in certain situations (e.g. as funciton
}
int main(void) {
apply_functors(FunctorA(),FunctorB());
apply_functors(FunctorA());
apply_functors([]()->void{ cout << "Lambda" << endl; });
return 0;
}
However this won't work because we are only allowed to expand parameter packs in certain situations and free like this is not one.
Attempt 2
My next idea was to make a dummy function which did nothing but into which I could pass the functors as paramters then have them expanded. The reasoning behind this is that function paramters are one of the situations where we can expand paramter packs.
template<typename... Fs>
void _dummyF_impl(Fs... fs){}
template<typename... Fs>
void apply_functors(Fs... fs) {
_dummyF_impl( fs()... ); // only works if all functors return a value (else we get "invalid use of 'void'")
}
However, this will not work because the functors return void from their operator()s and we cannot pass void as parameters to functions.
Expanding argument pack inside a braced initializer has the added benefit of guaranteed left-to-right evaluation (which is not the case for function argument list). You should also consider using perfect forwarding, here's why.
#include <initializer_list> //
#include <utility> // std::forward
template<typename... Fs>
void apply_functors(Fs&&... fs)
{
auto list = { (std::forward<Fs>(fs)(), 0)... };
// ^^^^ deduced as std::initializer_list
}
The same thing in principle, but this time without the necessary inclusion of <initializer_list> is a variadic template constructor which you can also call with braced initializer:
struct dummy {
template<typename... Fs>
dummy(Fs&&... fs) { }
};
template<typename... Fs>
void apply_functors(Fs&&... fs)
{
dummy { (std::forward<Fs>(fs)(), 0)... }; // evaluated left-to-right, too
}
I would do this way
template<typename... Fs>
void apply_functors(Fs... fs) {
int i[] = { ((void) fs(), 0)... };
(void) i; // prevents a warning about i not being used.
}
One of the situations that parameter pack expansion occurs is inside brace initializers. Above I used it in an array initialization.
The pattern (fs(), 0)... is expanded to (f1(), 0), (f2(), 0), ..., (fn(), 0) where f1, ..., fn are the provided callable objects. Notice that evaluating the expression (f1(), 0) calls f1(), ignores its returned value and the result of the expression is the 0 (an int).
The more complicated pattern ((void) fs(), 0)... is required to prevent a corner case namely when fs() returns a type for which the comma operator is overloaded.
The extra advantage with respect to the solution that uses the dummy function is that the order in which function arguments are evaluated is not specified by the standard while in the array initialization it is (from left to right). For instance, notice that calling apply_functors(FunctorA(),FunctorB()); in Dan's solution outputs FunctorB before FunctorA whereas with this solution here the output is FunctorA followed by FunctorB.
Update: After reading jrok's solution I realized the need for perfect forwarding. So my updated solution would be
template<typename... Fs>
void apply_functors(Fs&&... fs) {
int i[] = { ((void) std::forward<Fs>(fs)(), 0)... };
(void) i; // prevents a warning about i not being used.
}
My solution
The solution I found was the comma operator. I have never really had cause to use this before but it fits nicely here.
The comma operator can be used to evaluate separate statements but then "returns" the value of the last expression, so a,b,c evaluates to c.
Thus we can use this to evaluate our functors, disregard the void return value, then return something which is passed to _dummyF_impl:
template<typename... Fs>
void apply_functors(Fs... fs) {
_dummyF_impl( (fs(),0)... );
}
This compiles fine under g++ 4.7.3 and when run the output is as we would expect:
FunctorB
FunctorA
FunctorA
Lambda
Related
I would like to do
template<typename... ArgTypes> void print(ArgTypes... Args)
{
print(Args)...;
}
And have it be equivalent to this quite bulky recursive chain:
template<typename T, typename... ArgTypes> void print(const T& t, ArgTypes... Args)
{
print(t);
print(Args...);
}
followed by explicit single-parameter specializations for every type I'd like to print.
The "problem" with the recursive implementation is that a lot of redundant code is generated, because each recursive step results in a new function of N-1 arguments, whereas the code I'd like to have would only generate code for a single N-arg print function, and have at most N specialized print functions.
C++17 fold expression
(f(args), ...);
If you call something that might return an object with overloaded comma operator use:
((void)f(args), ...);
Pre-C++17 solution
The typical approach here is to use a dumb list-initializer and do the expansion inside it:
{ print(Args)... }
Order of evaluation is guaranteed left-to-right in curly initialisers.
But print returns void so we need to work around that. Let's make it an int then.
{ (print(Args), 0)... }
This won't work as a statement directly, though. We need to give it a type.
using expand_type = int[];
expand_type{ (print(Args), 0)... };
This works as long as there is always one element in the Args pack. Zero-sized arrays are not valid, but we can work around that by making it always have at least one element.
expand_type{ 0, (print(Args), 0)... };
We can make this pattern reusable with a macro.
namespace so {
using expand_type = int[];
}
#define SO_EXPAND_SIDE_EFFECTS(PATTERN) ::so::expand_type{ 0, ((PATTERN), 0)... }
// usage
SO_EXPAND_SIDE_EFFECTS(print(Args));
However, making this reusable requires a bit more attention to some details. We don't want overloaded comma operators to be used here. Comma cannot be overloaded with one of the arguments void, so let's take advantage of that.
#define SO_EXPAND_SIDE_EFFECTS(PATTERN) \
::so::expand_type{ 0, ((PATTERN), void(), 0)... }
If you are paranoid afraid of the compiler allocating large arrays of zeros for naught, you can use some other type that can be list-initialised like that but stores nothing.
namespace so {
struct expand_type {
template <typename... T>
expand_type(T&&...) {}
};
}
C++17 fold expression:
(f(args), ...);
Keep simple things simple ;-)
If you call something that might return an object with overloaded comma operator use:
((void)f(args), ...);
You can use even more simple and readable approach
template<typename... ArgTypes> void print(ArgTypes... Args)
{
for (const auto& arg : {Args...})
{
print(arg);
}
}
I have played with both variants on compile explorer and both gcc and clang with O3 or O2 produce exactly the same code but my variant is obviously cleaner.
I recently stumbled upon std::is_invocable that is going to be introduced into the C++17 standard and I am wondering why it needs a user to provide a type for a function pointer as opposed to just providing the function pointer itself which might be more convenient, especially since non type template parameters can now be unconstrained.
What I mean can be explained in the example below
void hello_world() {
cout << "Hello world" << endl;
}
int main() {
cout << std::is_invocable_v<decltype(hello_world)> << endl;
// as opposed to being able to do
// cout << std::is_invocable_v<hello_world> << endl;
return 0;
}
I am wondering why it needs a user to provide a type for a function pointer as opposed to just providing the function pointer itself which might be more convenient
Because you always have the type of the callable that you want to test, but you don't always have the value of it as a constant expression. Sure, when you do have the value you have to write out decltype(foo) instead of just foo, but that seems like a fairly minor burden, and would cover a fairly percentage of the use-case. Not sure it'd be worth the added complexity of having a template <auto F, class... Args> is_invocable just so that, sometimes, you as the user don't have to write decltype.
The primary use for std::is_invocable is to use with types and template parameters. Not to be only usable by directly using function pointers.
Let's change your code a bit and add a useful case:
void callF(F function, Args&& args) {
std::invoke(function, std::forward<Args>(args)...);
}
// Later, in your main
callF(hello_world);
You'd like to filter your function to not be callable when the invoke call would be invalid. You can use std::is_invokable just like that:
auto callF(F function, Args&& args) -> std::enable_if<std::is_invocable_v<F, Args...>> {
std::invoke(function, std::forward<Args>(args)...);
}
As you can see, the types sent as arguments to std::is_invocable reflect the arguments sent to std::invoke.
As a bonus, much more than function pointers are supported. Function objects too, and even member function pointers are supported. Right now, you could use the callF function like that:
callF([](int i){ /* ... */ }, 8);
struct Test { void test() {} };
Test t;
callF(&Test::test, t);
Given the following code, what is the reason behind the ambiguity? Can I circumvent it or will I have to keep the (annoying) explicit casts?
#include <functional>
using namespace std;
int a(const function<int ()>& f)
{
return f();
}
int a(const function<int (int)>& f)
{
return f(0);
}
int x() { return 22; }
int y(int) { return 44; }
int main()
{
a(x); // Call is ambiguous.
a(y); // Call is ambiguous.
a((function<int ()>)x); // Works.
a((function<int (int)>)y); // Works.
return 0;
}
Interestingly, if I comment out the a() function with the function<int ()> parameter and call a(x) in my main, the compilation correctly fails because of the type mismatch between x and the argument function<int (int)> of the only a() function available. If the compiler fails in that case, why would there be any ambiguity when the two a() functions are present?
I've tried with VS2010 and g++ v. 4.5. Both give me the exact same ambiguity.
The problem is that both function<int()> and function<int(int)> are constructible from the same function. This is what the constructor declaration of std::function looks like in VS2010:
template<class _Fx>
function(_Fx _Func, typename _Not_integral<!_Is_integral<_Fx>::value, int>::_Type = 0);
Ignoring the SFINAE part, it is constructible from pretty much anything.
std::/boost::function employ a technique called type erasure, to allow arbitary objects/functions to be passed in, so long they satisfy the signature when being called. One drawback from that is, that you get an error in the deepest part of the implementation (where the saved function is being called) when supplying an object which can't be called like the signature wants it to, instead of in the constructor.
The problem can be illustrated with this little class:
template<class Signature>
class myfunc{
public:
template<class Func>
myfunc(Func a_func){
// ...
}
};
Now, when the compiler searches for valid functions for the overload set, it tries to convert the arguments if no perfect fitting function exists. The conversion can happen through the constructor of the parameter of the function, or through a conversion operator of the argument given to the function. In our case, it's the former.
The compiler tries the first overload of a. To make it viable, it needs to make a conversion. To convert a int(*)() to a myfunc<int()>, it tries the constructor of myfunc. Being a template that takes anything, the conversion naturally succeeds.
Now it tries the same with the second overload. The constructor still being the same and still taking anything given to it, the conversion works too.
Being left with 2 functions in the overload set, the compiler is a sad panda and doesn't know what to do, so it simply says the call is ambigious.
So in the end, the Signature part of the template does belong to the type when making declarations/definitions, but doesn't when you want to construct an object.
Edit:
With all my attention on answering the title-question, I totally forgot about your second question. :(
Can I circumvent it or will I have to keep the (annoying) explicit casts?
Afaik, you have 3 options.
Keep the cast
Make a function object of the appropriate type and pass that
function<int()> fx = x;
function<int(int)> fy = y;
a(fx);
a(fy);
Hide the tedious casting in a function and use TMP to get the right signature
The TMP (template metaprogramming) version is quite verbose and with boilerplate code, but it hides the casting from the client. An example version can be found here, which relies on the get_signature metafunction that is partially specialized on function pointer types (and provides a nice example how pattern matching can work in C++):
template<class F>
struct get_signature;
template<class R>
struct get_signature<R(*)()>{
typedef R type();
};
template<class R, class A1>
struct get_signature<R(*)(A1)>{
typedef R type(A1);
};
Of course, this needs to be extended for the number of arguments you want to support, but that is done once and then buried in a "get_signature.h" header. :)
Another option I consider but immediatly discarded was SFINAE, which would introduce even more boilerplate code than the TMP version.
So, yeah, that are the options that I know of. Hope one of them works for you. :)
I've seen this question come up one too many times. libc++ now compiles this code without ambiguity (as a conforming extension).
Overdue Update
This "extension" proved sufficiently popular that it was standardized in C++14 (though I was not personally responsible for getting that job done).
In hindsight, I did not get this extension exactly correct. Earlier this month (2015-05-09) the committee voted in LWG issue 2420 which effectively changes the definition of Callable so that if the std::function has a void return type it will ignore the return type of the wrapped functor, but still otherwise consider it Callable if everything else matches up, instead of considering it not Callable.
This post-C++14 tweak does not impact this particular example since the return types involved are consistently int.
Here's an example of how to wrap std::function in a class that checks invokability of its constructor parameters:
template<typename> struct check_function;
template<typename R, typename... Args>
struct check_function<R(Args...)>: public std::function<R(Args...)> {
template<typename T,
class = typename std::enable_if<
std::is_same<R, void>::value
|| std::is_convertible<
decltype(std::declval<T>()(std::declval<Args>()...)),
R>::value>::type>
check_function(T &&t): std::function<R(Args...)>(std::forward<T>(t)) { }
};
Use like this:
int a(check_function<int ()> f) { return f(); }
int a(check_function<int (int)> f) { return f(0); }
int x() { return 22; }
int y(int) { return 44; }
int main() {
a(x);
a(y);
}
Note that this isn't quite the same as overloading on function signature, as it treats convertible argument (and return) types as equivalent. For exact overloading, this should work:
template<typename> struct check_function_exact;
template<typename R, typename... Args>
struct check_function_exact<R(Args...)>: public std::function<R(Args...)> {
template<typename T,
class = typename std::enable_if<
std::is_convertible<T, R(*)(Args...)>::value>::type>
check_function_exact(T &&t): std::function<R(Args...)>(std::forward<T>(t)) { }
};
std::function<T> has a conversion ctor that takes an arbitrary type (i.e., something other than a T). Sure, in this case, that ctor would result in a type mismatch error, but the compiler doesn't get that far -- the call is ambiguous simply because the ctor exists.
This question was asked to me in an interview:
Lets say you have a function which can take any kind of arguments and any number of arguments.
How would you write a template function for the same?
I do not know the exact answer. could anybody suggest?
They checked your awareness of the upcoming C++ standard. The new feature is called "Variadic templates" and looks like this:
template<typename... Args> void f( const Args&... args )
{
// do something
}
For a more complicated examples see, e.g. this tutorial.
In C++03, for any number of argument in function template is not possible. However, for any type of argument you can write:
template<typename T, typename U>
void f( const T & t, const U &u )
{
//...
}
I agree that they were most probably looking for variadic templates, but for the sake of it, different approaches that can be taken in C++03:
Using a variant type
Use a container of a variant type. In this case boost::variant will not work, as it limits the number of types, but you can use boost::any:
void foo( std::vector< boost::any > args );
Compared to variadic templates, user code will be much more cumbersome, as instead of writting foo( a, b, c, d ), they will have to manually create the vector upfront. The syntax could be simplified by means of variadic macros (if the compiler supports them) and or helper templated functions to adapt the syntax, but this can quite easily become a mess.
The C way (non-template):
Use the ellipsis notation to write a function that takes an unknown number of arguments (and types):
void foo( type x, ... )
This approach has many shortcommings. The first one is that it is not typesafe, the compiler will not be able to detect that the arguments are the correct number or types, and it is undefined behavior if any of the arguments is a non-POD type, which limits usability from any type to POD types, which might or not be a limiting factor (you can always pass in a pointer to your non-POD object). Overall this is more complex to handle, and much more error prone so it should be avoided.
Not answering the question at all
In very few situations a single function should be able to take an unknown number of arguments of unknown types. Logging and i/o can require this, printf being such example. But that can be handled in C++ by means of operator overloading (in particular operator<<) and chaining. In a comment bind has been suggested, so yes, perfect forwarding in generic code is one such case, bind, std::thread...
It think this to be a good answer for an interview, as you can then discuss what the actual need for the function is, and whether there is any better alternative. It can be argued that if at the end you do need a container of a variant type, you can abuse operator overloading to simplify the syntax. Examples of this would be the boost::assign library, and in those lines you can create a helper argument builder as in:
class args {
public:
args() {}
operator std::vector<boost::any>&() {
return v;
}
template <typename T>
args& operator,( T x ) {
boost::any a = x;
v.push_back( a );
return *this;
}
private:
std::vector<boost::any> v;
};
// usage:
void foo( std::vector<boost::any> a ) {
std::cout << "Received " << a.size() << " arguments" << std::endl;
}
int main() {
foo(( args(), 1, 5.0, "a string", std::vector<int>(5,10) ));
}
Variadic templates
And of course, the best option that is a c++0x compiler that handles variadic templates, that requires no extra boiler plate code, and will make it much simpler to write both user code (directly as a regular function call) and the implementation of the function, whatever it is. As a motivating example, building a vector<boost::any> with variadic args:
typedef std::vector<boost::any> anyvector_t
// Stop condition, adding nothing at the end
void build_vector_impl( anyvector_t& ) {}
// Intermediate step, add a new argument to the vector and recurse:
template <typename Head, typename... Tail>
void build_vector_impl( anyvector_t& v, Head head, Tail... tail ) {
v.push_back( boost::any(head) );
build_vector_impl( v, tail... );
}
// Syntactic sugar: make it return the vector:
template <typename... Args>
anyvector_t build_vector( Args... args ) {
anyvector_t res;
build_vector_impl( res, args... );
return res;
}
// Test:
int main() {
std::cout << "Number of args: "
<< build_vector( 1, 5, "Hi", std::vector<int>( 5, 10 ) ).size()
<< std::endl;
}
That is not about templates. It's about variable arguments.
http://www.eskimo.com/~scs/cclass/int/sx11b.html
Given the following code, what is the reason behind the ambiguity? Can I circumvent it or will I have to keep the (annoying) explicit casts?
#include <functional>
using namespace std;
int a(const function<int ()>& f)
{
return f();
}
int a(const function<int (int)>& f)
{
return f(0);
}
int x() { return 22; }
int y(int) { return 44; }
int main()
{
a(x); // Call is ambiguous.
a(y); // Call is ambiguous.
a((function<int ()>)x); // Works.
a((function<int (int)>)y); // Works.
return 0;
}
Interestingly, if I comment out the a() function with the function<int ()> parameter and call a(x) in my main, the compilation correctly fails because of the type mismatch between x and the argument function<int (int)> of the only a() function available. If the compiler fails in that case, why would there be any ambiguity when the two a() functions are present?
I've tried with VS2010 and g++ v. 4.5. Both give me the exact same ambiguity.
The problem is that both function<int()> and function<int(int)> are constructible from the same function. This is what the constructor declaration of std::function looks like in VS2010:
template<class _Fx>
function(_Fx _Func, typename _Not_integral<!_Is_integral<_Fx>::value, int>::_Type = 0);
Ignoring the SFINAE part, it is constructible from pretty much anything.
std::/boost::function employ a technique called type erasure, to allow arbitary objects/functions to be passed in, so long they satisfy the signature when being called. One drawback from that is, that you get an error in the deepest part of the implementation (where the saved function is being called) when supplying an object which can't be called like the signature wants it to, instead of in the constructor.
The problem can be illustrated with this little class:
template<class Signature>
class myfunc{
public:
template<class Func>
myfunc(Func a_func){
// ...
}
};
Now, when the compiler searches for valid functions for the overload set, it tries to convert the arguments if no perfect fitting function exists. The conversion can happen through the constructor of the parameter of the function, or through a conversion operator of the argument given to the function. In our case, it's the former.
The compiler tries the first overload of a. To make it viable, it needs to make a conversion. To convert a int(*)() to a myfunc<int()>, it tries the constructor of myfunc. Being a template that takes anything, the conversion naturally succeeds.
Now it tries the same with the second overload. The constructor still being the same and still taking anything given to it, the conversion works too.
Being left with 2 functions in the overload set, the compiler is a sad panda and doesn't know what to do, so it simply says the call is ambigious.
So in the end, the Signature part of the template does belong to the type when making declarations/definitions, but doesn't when you want to construct an object.
Edit:
With all my attention on answering the title-question, I totally forgot about your second question. :(
Can I circumvent it or will I have to keep the (annoying) explicit casts?
Afaik, you have 3 options.
Keep the cast
Make a function object of the appropriate type and pass that
function<int()> fx = x;
function<int(int)> fy = y;
a(fx);
a(fy);
Hide the tedious casting in a function and use TMP to get the right signature
The TMP (template metaprogramming) version is quite verbose and with boilerplate code, but it hides the casting from the client. An example version can be found here, which relies on the get_signature metafunction that is partially specialized on function pointer types (and provides a nice example how pattern matching can work in C++):
template<class F>
struct get_signature;
template<class R>
struct get_signature<R(*)()>{
typedef R type();
};
template<class R, class A1>
struct get_signature<R(*)(A1)>{
typedef R type(A1);
};
Of course, this needs to be extended for the number of arguments you want to support, but that is done once and then buried in a "get_signature.h" header. :)
Another option I consider but immediatly discarded was SFINAE, which would introduce even more boilerplate code than the TMP version.
So, yeah, that are the options that I know of. Hope one of them works for you. :)
I've seen this question come up one too many times. libc++ now compiles this code without ambiguity (as a conforming extension).
Overdue Update
This "extension" proved sufficiently popular that it was standardized in C++14 (though I was not personally responsible for getting that job done).
In hindsight, I did not get this extension exactly correct. Earlier this month (2015-05-09) the committee voted in LWG issue 2420 which effectively changes the definition of Callable so that if the std::function has a void return type it will ignore the return type of the wrapped functor, but still otherwise consider it Callable if everything else matches up, instead of considering it not Callable.
This post-C++14 tweak does not impact this particular example since the return types involved are consistently int.
Here's an example of how to wrap std::function in a class that checks invokability of its constructor parameters:
template<typename> struct check_function;
template<typename R, typename... Args>
struct check_function<R(Args...)>: public std::function<R(Args...)> {
template<typename T,
class = typename std::enable_if<
std::is_same<R, void>::value
|| std::is_convertible<
decltype(std::declval<T>()(std::declval<Args>()...)),
R>::value>::type>
check_function(T &&t): std::function<R(Args...)>(std::forward<T>(t)) { }
};
Use like this:
int a(check_function<int ()> f) { return f(); }
int a(check_function<int (int)> f) { return f(0); }
int x() { return 22; }
int y(int) { return 44; }
int main() {
a(x);
a(y);
}
Note that this isn't quite the same as overloading on function signature, as it treats convertible argument (and return) types as equivalent. For exact overloading, this should work:
template<typename> struct check_function_exact;
template<typename R, typename... Args>
struct check_function_exact<R(Args...)>: public std::function<R(Args...)> {
template<typename T,
class = typename std::enable_if<
std::is_convertible<T, R(*)(Args...)>::value>::type>
check_function_exact(T &&t): std::function<R(Args...)>(std::forward<T>(t)) { }
};
std::function<T> has a conversion ctor that takes an arbitrary type (i.e., something other than a T). Sure, in this case, that ctor would result in a type mismatch error, but the compiler doesn't get that far -- the call is ambiguous simply because the ctor exists.