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
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);
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
I have been trying to implement in C++11 the function map from Python. It seems to work for any kind of callable objet, but I have to specify the template type parameter if I want it to work with function templates. Example:
#include <iostream>
#include <list>
template<typename T>
T abs(T x)
{
return x < 0 ? -x : x;
}
int main()
{
std::list<int> li = { -1, -2, -3, -4, -5 };
for (auto i: map(&abs<int>, li))
{
std::cout << i << std::endl;
}
}
It works fine, but I would like it to deduce the int parameter from the second argument of the function, and hence be able to write:
for (auto i: map(&abs, li))
{
std::cout << i << std::endl;
}
My map function is written as:
template<typename Callable, typename Container>
auto map(const Callable& function, Container&& iter)
-> MapObject<Callable, Container>
{
return { function, std::forward<Container>(iter) };
}
where MapObject is part of the implmentation and not a real problem here. How could I change its definition so that the template type of the Callable object can be deduced from the Container object? For example, how can map know that we have to use abs<int> for a given abs when a list<int> is given?
It works fine, but I would like it to deduce the int parameter from the second argument of the function, and hence be able to write:
for (auto i: map(&abs, li))
{
std::cout << i << std::endl;
}
The problem is that abs is not a function, but a function template, and thus there is no address-of abs, although there is &abs<int>, since abs<int> (specialization) is indeed a function (generated from a template).
Now the question is what you really want to solve, and in particular you must realize that C++ is a statically typed language where python is a dynamically typed language. It is unclear to me what you are trying to achieve here on different levels. For example, the function map in python has an equivalent in std::transform in C++:
a = [ 1, 2, 3 ]
a = map(lambda x: 2*x, a)
std::vector<int> v{1,2,3};
std::transform(v.begin(),v.end(),v.begin(),[](int x){ return 2*x; });
Where I have cheated slightly because in python it will create a different container yet in C++ transform works at the iterator level and knows of no container, but you can get the same effect similarly:
std::vector<int> v{1,2,3};
std::vector<int> result;
// optionally: result.reserve(v.size());
std::transform(v.begin(),v.end(),
std::back_inserter(result),
[](int x) { return 2*x; });
I'd advice that you learn the idioms in the language rather than trying to implement idioms from other languages...
BTW, if you are willing to have the user specify the type of the functor that is passed to the map function, then you can just pass the name of the template and let the compiler figure out what specialization you need:
template <typename Container>
auto map(Container && c,
typename Container::value_type (*f)(typename Container::value_type))
-> MapObject<Callable<T>,Container>;
template <typename T>
T abs(T value);
int main() {
std::vector<int> v{1,2,3,4};
map(v,abs);
}
This is less generic than what you were trying to do, as it only accepts function pointers and of concrete type (this is even less generic than std::transform) and it works as when the compiler sees abs (without the &) it will resolve it to the template, and thus to the set of specializations. It will then use the expected type to select one specialization and pass it in. The compiler will implicitly do &abs<int> for you in this case.
Another more generic alternative is not using functions, but functors. With this in mind you can define abs as:
struct abs {
template <typename T>
T operator()(T t) { ...}
};
And then pass a copy of the functor in instead of the function pointer. There is no need to determine the overload to be used where you pass the object abs into the map function, only when it is used. The caller side would look like:
for (auto& element : map(container,abs()))
Where the extra set of parenthesis is creating an object of type abs and passing it in.
Overall, I would try to avoid this. It is a fun thing to do, and you can probably get to a good solution, but it will be hard and require quite a bit of c++ expertise. Because it is not supported by the language, you will have to design something that works within the language and that requires compromises on different features or syntax. Knowing the options is a hard problem in itself, understanding the compromises even harder and getting to a good solution much harder. And the good solution will probably be worse than the equivalent idiomatic C++ code.
If you program in C++, program C++. Trying to code python through a C++ compiler will probably give you the pain of C++ and the performance of python.
It doesn't deduce it because you never specified that Callable is a template. You make Callable a template template parameter and it should deduce its type for you.
template<template <typename T> typename Callable, typename Container>
auto map(const Callable<T>& function, Container&& iter)
-> MapObject<Callable<T>, Container>
{
return { function, std::forward<Container>(iter) };
}
You might get bitten though as you can't take the address of a template still to be instantiated. Not sure why you need the address-of though...
A function named test takes std::function<> as its parameter.
template<typename R, typename ...A>
void test(std::function<R(A...)> f)
{
// ...
}
But, if I do the following:
void foo(int n) { /* ... */ }
// ...
test(foo);
Compiler(gcc 4.6.1) says no matching function for call to test(void (&)(int)).
To make the last line test(foo) compiles and works properly, how can I modify the test() function? In test() function, I need f with type of std::function<>.
I mean, is there any template tricks to let compiler determine the signature of function(foo in example), and convert it to std::function<void(int)> automatically?
EDIT
I want to make this work for lambdas (both stateful and stateless) as well.
It looks like you want to use overloading
template<typename R, typename ...A>
void test(R f(A...))
{
test(std::function<R(A...)>(f));
}
This simple implementation will accept most if not all the functions you will try to pass. Exotic functions will be rejected (like void(int...)). More work will give you more genericity.
std::function implements the Callable interface, i.e. it looks like a function, but that doesn't mean you should require callable objects to be std::functions.
template< typename F > // accept any type
void test(F const &f) {
typedef std::result_of< F( args ) >::type R; // inspect with traits queries
}
Duck typing is the best policy in template metaprogramming. When accepting a template argument, be unspecific and just let the client implement the interface.
If you really need a std::function for example to re-target the variable or something crazy like that, and you know the input is a raw function pointer, you can decompose a raw function pointer type and reconsitute it into a std::function.
template< typename R, typename ... A >
void test( R (*f)( A ... ) ) {
std::function< R( A ... ) > internal( f );
}
Now the user can't pass a std::function because that has been encapsulated within the function. You could keep your existing code as another overload and just delegate to that, but be careful to keep interfaces simple.
As for stateful lambdas, I don't know how to handle that case. They don't decompose to function pointers and as far as I know the argument types cannot be queried or deduced. This information is necessary to instantiate std::function, for better or worse.
This is an old one, and I can't seem to find much on the same topic, so I thought I would go ahead and put in a note.
Compiled on GCC 4.8.2, the following works:
template<typename R, typename... A>
R test(const std::function<R(A...)>& func)
{
// ...
}
However, you can't just call it by passing in your pointers, lambdas, etc. However, the following 2 examples both work with it:
test(std::function<void(int, float, std::string)>(
[](int i, float f, std::string s)
{
std::cout << i << " " << f << " " << s << std::endl;
}));
Also:
void test2(int i, float f, std::string s)
{
std::cout << i << " " << f << " " << s << std::endl;
}
// In a function somewhere:
test(std::function<void(int, float, std::string)>(&test2));
The downside of these should stand out pretty obviously: you have to explicitly declare the std::function for them, which might look a little bit ugly.
That said, though, I threw that together with a tuple that gets expanded to call the incoming function, and it works, just requiring a little bit more of an explicitly saying what you're doing calling the test function.
Example code including the tuple thing, if you want to play with it: http://ideone.com/33mqZA
It's usually ill-advised to accept std::function by value unless you are at 'binary delimitation' (e.g. dynamic library, 'opaque' API) since as you've just witnessed they play havoc with overloading. When a function does in fact take an std::function by value then it's often the burden of the caller to construct the object to avoid the overloading problems (if the function is overloaded at all).
Since however you've written a template, it's likely the case that you're not using std::function (as a parameter type) for the benefits of type-erasure. If what you want to do is inspecting arbitrary functors then you need some traits for that. E.g. Boost.FunctionTypes has traits such as result_type and parameter_types. A minimal, functional example:
#include <functional>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_type.hpp>
template<typename Functor>
void test(Functor functor) // accept arbitrary functor!
{
namespace ft = boost::function_types;
typedef typename ft::result_type<Functor>::type result_type;
typedef ft::parameter_types<Functor> parameter_types;
typedef typename boost::mpl::push_front<
parameter_types
, result_type
>::type sequence_type;
// sequence_type is now a Boost.MPL sequence in the style of
// mpl::vector<int, double, long> if the signature of the
// analyzed functor were int(double, long)
// We now build a function type out of the MPL sequence
typedef typename ft::function_type<sequence_type>::type function_type;
std::function<function_type> function = std::move(functor);
}
As a final note, I do not recommend introspecting functors (i.e. prodding for their result type and argument types) in the general case as that simply don't work for polymorphic functors. Consider several overloaded operator(): then there is no 'canonical' result type or argument types. With C++11 it's better to 'eagerly' accept any kind of functor, or constrain them using techniques like SFINAE or static_assert depending on the needs, and later on (when parameters are available) to use std::result_of to inspect the result type for a given set of arguments. A case where constraining up front is desirable is when the aim is to store functors into e.g. a container of std::function<Sig>.
To get a taste of what I mean by the previous paragraph it's enough to test the above snippet with polymorphic functors.