Related
I am a little confused about how can I read each argument from the tuple by using variadic templates.
Consider this function:
template<class...A> int func(A...args){
int size = sizeof...(A);
.... }
I call it from the main file like:
func(1,10,100,1000);
Now, I don't know how I have to extend the body of func to be able to read each argument separately so that I can, for example, store the arguments in an array.
You have to provide overrides for the functions for consuming the first N (usually one) arguments.
void foo() {
// end condition argument pack is empty
}
template <class First, class... Rest>
void foo(First first, Rest... rest) {
// Do something with first
cout << first << endl;
foo(rest...); // Unpack the arguments for further treatment
}
When you unpack the variadic parameter it finds the next overload.
Example:
foo(42, true, 'a', "hello");
// Calls foo with First = int, and Rest = { bool, char, char* }
// foo(42, Rest = {true, 'a', "hello"}); // not the real syntax
Then next level down we expand the previous Rest and get:
foo(true, Rest = { 'a', "hello"}); // First = bool
And so on until Rest contains no members in which case unpacking it calls foo() (the overload with no arguments).
Storing the pack if different types
If you want to store the entire argument pack you can use an std::tuple
template <class... Pack>
void store_pack(Pack... p) {
std::tuple<Pack...> store( p... );
// do something with store
}
However this seems less useful.
Storing the pack if it's homogeneous
If all the values in the pack are the same type you can store them all like this:
vector<int> reverse(int i) {
vector<int> ret;
ret.push_back(i);
return ret;
}
template <class... R>
vector<int> reverse(int i, R... r) {
vector<int> ret = reverse(r...);
ret.push_back(i);
return ret;
}
int main() {
auto v = reverse(1, 2, 3, 4);
for_each(v.cbegin(), v.cend(),
[](int i ) {
std::cout << i << std::endl;
}
);
}
However this seems even less useful.
If the arguments are all of the same type, you could store the arguments in an array like this (using the type of the first argument for the array):
template <class T, class ...Args>
void foo(const T& first, const Args&... args)
{
T arr[sizeof...(args) + 1] = { first, args...};
}
int main()
{
foo(1);
foo(1, 10, 100, 1000);
}
If the types are different, I suppose you could use boost::any but then I don't see how you are going to find out outside of the given template, which item is of which type (how you are going to use the stored values).
Edit:
If the arguments are all of the same type and you want to store them into a STL container, you could rather use the std::initializer_list<T>. For example, Motti's example of storing values in reverse:
#include <vector>
#include <iostream>
#include <iterator>
template <class Iter>
std::reverse_iterator<Iter> make_reverse_iterator(Iter it)
{
return std::reverse_iterator<Iter>(it);
}
template <class T>
std::vector<T> reverse(std::initializer_list<T> const & init)
{
return std::vector<T>(make_reverse_iterator(init.end()), make_reverse_iterator(init.begin()));
}
int main() {
auto v = reverse({1, 2, 3, 4});
for (auto it = v.begin(); it != v.end(); ++it) {
std::cout << *it << std::endl;
}
}
For sticking into an array if the arguments have different types, you can use also std::common_type<>
template<class ...A> void func(A ...args){
typedef typename std::common_type<A...>::type common;
std::array<common, sizeof...(A)> a = {{ args... }};
}
So for example, func(std::string("Hello"), "folks") creates an array of std::string.
If you need to store arguments in the array you could use array of boost::any as follows:
template<typename... A> int func(const A&... args)
{
boost::any arr[sizeof...(A)] = { args... };
return 0;
}
I come from a Swift background and, though I know some C as well, this is my first time writing C++ code.
In Swift it is possible to write a function that takes any number of arguments:
func foo(bar: String...) {
// ...
}
and bar can be of any type (String, Bool, Struct, Enum, etc).
I was wondering if the same can be done in C++. So, ideally I would write:
struct X {
string s;
X(int);
// ...
}
void foo(string s, ...) {
// ...
}
foo("mystr", X(1), X(2), X(3));
and inside foo I would somehow be able to access the list of arguments, somewhat akin to a printf function.
Right now I'm using a vector<X> as argument, since all the arguments have type X. However, that makes calling foo somewhat ugly, in my opinion:
foo("mystr", { X(1), X(2), X(3) });
Any solution I'm not seeing due to my strong lack of knowledge towards C++?
Edit:
This is what I want done specifically inside foo:
string ssub(string s, vector<X> v) {
int index, i = 0;
while (1) {
index = (int)s.find(SUB);
if (index == string::npos) { break; }
s.erase(index, string(SUB).size());
s.insert(index, v[i].tostr());
i++;
}
return s;
}
Basically, as long as I'm given a way to sequentially access the arguments, all is good.
Here's one of many ways.
You can copy/paste this entire program into your IDE/editor.
#include <utility>
#include <iostream>
#include <typeinfo>
#include <string>
//
// define a template function which applies the unary function object func
// to each element in the parameter pack elems.
// #pre func(std::forward<Elements>(elems)) must be well formed for each elems
// #returns void
//
template<class Function, class...Elements>
auto do_for_all(Function&& func, Elements&&...elems)
{
using expand = int[];
void(expand { 0, (func(elems), 0)... });
}
// a test structure which auto-initialises all members
struct X
{
int i = 0;
std::string s = "hello";
double d = 4.4;
};
//
// The function foo
// introduces itself by writing intro to the console
// then performs the function object action on each of args
// #note all arguments are perfectly forwarded - no arguments are copied
//
template<class...Args>
auto foo(const std::string& intro, Args&&...args)
{
std::cout << "introducing : " << intro << std::endl;
auto action = [](auto&& arg)
{
std::cout << "performing action on: " << arg
<< " which is of type " << typeid(arg).name() << std::endl;
};
do_for_all(action, std::forward<Args>(args)...);
}
int main()
{
// make an X
auto x = X(); // make an X
// foo it with the intro "my X"
foo("my X", x.i, x.s, x.d);
}
example output:
introducing : my X
performing action on: 0 which is of type i
performing action on: hello which is of type NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
performing action on: 4.4 which is of type d
You can use variadic templates (since C++11):
template <typename ... Type>
void foo(Type& ... args) {
// do whatever you want, but this may be tricky
}
foo(X(1), X(2), X(3));
Example of variadic templates: min function
This is the code I wrote to get rid of ugly calls to std::min when calculating minimum of many values.
#include <type_traits>
namespace my {
template <typename A, typename B>
auto min(const A& a, const B& b) -> typename std::common_type<A, B>::type {
return (a<b)?a:b;
}
template <typename A, typename B, typename ... T >
auto min(const A& a, const B& b, const T& ... c) -> typename std::common_type<A, B, T ...>::type {
const typename std::common_type<A, B, T ...>::type tmp = my::min(b, c ...);
return (a<tmp)?a:tmp;
}
}
// calculating minimum with my::min
my::min(3, 2, 3, 5, 23, 98);
// doing the same with std::min
std::min(3, std::min(2, std::min(3, std::min(5, std::min(23, 98))))); // ugh, this is ugly!
Here's the tricky part: you can't cycle through the parameter pack like you do with vectors. You'll have to do some recursion as shown in the example.
You could write a variadic template function, pass the arguments into some std::initializer_list and iterate over the list, for example:
#include <initializer_list>
template <typename ... Args>
void foo(Args && ... args) {
std::initializer_list<X> as{std::forward<Args>(args)...};
for (auto const & x : as)
// Use x here
}
int main() {
foo(1, 2, 3, 4, 5);
}
Note also, that you might want to change the argument list and type of the initializer list to meet your exact use-case. E.g. use Args * ... args and std::initializer_list<X *> or similar.
Here is code that I hope explains what I want to achieve.
vector<int> ints;
vector<double> doubles;
struct Arg {
enum Type {
Int,
Double
};
Type type;
int index;
};
template <typename F>
void Call(const F& f, const vector<Arg>& args) {
// TODO:
// - First assert that count and types or arguments of <f> agree with <args>.
// - Call "f(args)"
}
// Example:
void copy(int a, double& b) {
b = a;
}
int test() {
Call(copy, {{Int, 3}, {Double, 2}}); // copy(ints[3], double[2]);
}
Can this be done in C++11 ?
If yes, can the solution be simplified in C++14 ?
I'd do this in two steps.
First, I'd wrap f in an object able to understand Arg-like parameters, and generate errors on failure. For simplicity, suppose we throw.
This is a bit simpler than your Arg to be understood at this layer, so I might translate Arg into MyArg:
struct MyArg {
MyArg(MyArg const&)=default;
MyArg(int* p):i(p){}
MyArg(double* p):d(p){}
MyArg(Arg a):MyArg(
(a.type==Arg::Int)?
MyArg(&ints.at(a.index)):
MyArg(&doubles.at(a.index))
) {}
int * i = nullptr;
double* d = nullptr;
operator int&(){ if (!i) throw std::invalid_argument(""); return *i; }
operator double&(){ if (!d) throw std::invalid_argument(""); return *d; }
};
We map void(*)(Ts...) to std::function<void(MyArg, MyArg, MyArg)> like this:
template<class T0, class T1>using second_type = T1;
template<class...Ts>
std::function<void( second_type<Ts,MyArg>... )> // auto in C++14
my_wrap( void(*f)(Ts...) ) {
return [f](second_type<Ts,MyArg>...args){
f(args...);
};
}
now all that is left is counting function parameter count vs vector size count, and unpacking the std::vector into a function call.
The last looks like:
template<class...Ts, size_t...Is>
void call( std::function<void(Ts...)> f, std::index_sequence<Is...>, std::vector<Arg> const& v ) {
f( v[Is]... );
}
template<class...Ts>
void call( std::function<void(Ts...)> f, std::vector<Arg> const& v ) {
call( std::move(f), std::index_sequence_for<Ts...>{}, v );
}
where index_sequence and index_sequence_for are C++14, but equivalents can be implemented in C++11 (there are many implementations on stack overflow).
So we end up with something like:
template<class...Ts>
void Call( void(*pf)(Ts...), std::vector<Arg> const& v ) {
if (sizeof...(Ts)>v.size())
throw std::invalid_argument("");
auto f = my_wrap(pf);
call( std::move(f), v );
}
Dealing with the throws is left as an exercise, as is handling return values.
This code has not been compiled or tested, but the design should be sound. It only supports calling function pointers -- calling generalized callable objects is tricky, because counting how many arguments they want (of type int or double) is tricky. If you passed in how many arguments they want as a compile-time constant, it is easy. You could also build a magic switch that handles counts up to some constant (10, 20, 1000, whatever), and dispatch the runtime length of the vector into a compile time constant that throws on a argument length mismatch.
This is trickier.
The hard coded pointers sort of suck.
template<class...Ts>struct types{using type=types;};
template<size_t I> using index=std::integral_constant<size_t, I>;
template<class T, class types> struct index_in;
template<class T, class...Ts>
struct index_in<T, types<T,Ts...>>:
index<0>
{};
template<class T, class T0, class...Ts>
struct index_in<T, types<T0,Ts...>>:
index<1+index_in<T, types<Ts...>>{}>
{};
is a package of types.
Here is how we can store buffers:
template<class types>
struct buffers;
template<class...Ts>
struct buffers<types<Ts...>> {
struct raw_view {
void* start = 0;
size_t length = 0;
};
template<class T>
struct view {
T* start = 0;
T* finish = 0;
view(T* s, T* f):start(s), finish(f) {}
size_t size() const { return finish-start; }
T& operator[](size_t i)const{
if (i > size()) throw std::invalid_argument("");
return start[i];
}
}
std::array< raw_view, sizeof...(Ts) > views;
template<size_t I>
using T = std::tuple_element_t< std::tuple<Ts...>, I >;
template<class T>
using I = index_of<T, types<Ts...> >;
template<size_t I>
view<T<I>> get_view() const {
raw_view raw = views[I];
if (raw.length==0) { return {0,0}; }
return { static_cast<T<I>*>(raw.start), raw.length/sizeof(T) };
}
template<class T>
view<T> get_view() const {
return get_view< I<T>{} >();
}
template<class T>
void set_view( view<T> v ) {
raw_view raw{ v.start, v.finish-v.start };
buffers[ I<T>{} ] = raw;
}
};
now we modify Call:
template<class R, class...Args, size_t...Is, class types>
R internal_call( R(*f)(Args...), std::vector<size_t> const& indexes, buffers<types> const& views, std::index_sequence<Is...> ) {
if (sizeof...(Args) != indexes.size()) throw std::invalid_argument("");
return f( views.get_view<Args>()[indexes[Is]]... );
}
template<class R, class...Args, size_t...Is, class types>
R Call( R(*f)(Args...), std::vector<size_t> const& indexes, buffers<types> const& views ) {
return internal_call( f, indexes, views, std::index_sequence_for<Args...>{} );
}
which is C++14, but most components can be translated to C++11.
This uses O(1) array lookups, no maps. You are responsible for populating buffers<types> with the buffers, sort of like this:
buffers<types<double, int>> bufs;
std::vector<double> d = {1.0, 3.14};
std::vector<int> i = {1,2,3};
bufs.set_view<int>( { i.data(), i.data()+i.size() } );
bufs.set_view<double>( { d.data(), d.data()+d.size() } );
parameter mismatch counts and index out of range generate thrown errors. It only works with raw function pointers -- making it work with anything with a fixed (non-template) signature is easy (like a std::function).
Making it work with an object with no signature is harder. Basically instead of relying on the function called for the arguments, you instead build the cross product of the types<Ts...> up to some fixed size. You build a (large) table of which of these are valid calls to the passed in call target (at compile time), then at run time walk that table and determine if the arguments passed in are valid to call the object with.
It gets messy.
This is why my above version simply asks for indexes, and deduces the types from the object being called.
I have a partial solution, using C++11 grammar.
First I make a function overloader accepting arbitrator kinds of arguments
template< typename Function >
struct overloader : Function
{
overloader( Function const& func ) : Function{ func } {}
void operator()(...) const {}
};
template< typename Function >
overloader<Function> make_overloader( Function const& func )
{
return overloader<Function>{ func };
}
then, using the overloader to deceive the compiler into believing the following code ( in switch-case block )is legal:
template <typename F>
void Call( F const& f, const vector<Arg>& args )
{
struct converter
{
Arg const& arg;
operator double&() const
{
assert( arg.type == Double );
return doubles[arg.index];
}
operator int() const
{
assert( arg.type == Int );
return ints[arg.index];
}
converter( Arg const& arg_ ): arg( arg_ ) {}
};
auto function_overloader = make_overloader( f );
unsigned long const arg_length = args.size();
switch (arg_length)
{
case 0 :
function_overloader();
break;
case 1 :
function_overloader( converter{args[0]} );
break;
case 2 :
function_overloader( converter{args[0]}, converter{args[1]} );
break;
case 3 :
function_overloader( converter{args[0]}, converter{args[1]}, converter{args[2]} );
break;
/*
case 4 :
.
.
.
case 127 :
*/
}
}
and test it this way:
void test_1()
{
Call( []( int a, double& b ){ b = a; }, vector<Arg>{ Arg{Int, 3}, Arg{Double, 2} } );
}
void test_2()
{
Call( []( double& b ){ b = 3.14; }, vector<Arg>{ Arg{Double, 0} } );
}
void my_copy( int a, double& b, double& c )
{
b = a;
c = a+a;
}
void test_3()
{
//Call( my_copy, vector<Arg>{ Arg{Int, 4}, Arg{Double, 3}, Arg{Double, 1} } ); // -- this one does not work
Call( []( int a, double& b, double& c ){ my_copy(a, b, c); }, vector<Arg>{ Arg{Int, 4}, Arg{Double, 3}, Arg{Double, 1} } );
}
the problems with this solution is:
g++5.2 accept it, clang++6.1 doesn's
when the argument(s) of function Call is/are not legal, it remains silent
the first argument of function Call cannot be a C-style function, one must wrap that into a lambda object to make it work.
the code is available here - http://melpon.org/wandbox/permlink/CHZxVfLM92h1LACf -- for you to play with.
First of all, you need some mechanism to register your argument values that are later referenced by some type and an index:
class argument_registry
{
public:
// register a range of arguments of type T
template <class T, class Iterator>
void register_range(Iterator begin, Iterator end)
{
// enclose the range in a argument_range object and put it in our map
m_registry.emplace(typeid(T), std::make_unique<argument_range<T, Iterator>>(begin, end));
}
template <class T>
const T& get_argument(size_t idx) const
{
// check if we have a registered range for this type
auto itr = m_registry.find(typeid(T));
if (itr == m_registry.end())
{
throw std::invalid_argument("no arguments registered for this type");
}
// we are certain about the type, so downcast the argument_range object and query the argument
auto range = static_cast<const argument_range_base1<T>*>(itr->second.get());
return range->get(idx);
}
private:
// base class so we can delete the range objects properly
struct argument_range_base0
{
virtual ~argument_range_base0(){};
};
// interface for querying arguments
template <class T>
struct argument_range_base1 : argument_range_base0
{
virtual const T& get(size_t idx) const = 0;
};
// implements get by querying a registered range of arguments
template <class T, class Iterator>
struct argument_range : argument_range_base1<T>
{
argument_range(Iterator begin, Iterator end)
: m_begin{ begin }, m_count{ size_t(std::distance(begin, end)) } {}
const T& get(size_t idx) const override
{
if (idx >= m_count)
throw std::invalid_argument("argument index out of bounds");
auto it = m_begin;
std::advance(it, idx);
return *it;
}
Iterator m_begin;
size_t m_count;
};
std::map<std::type_index, std::unique_ptr<argument_range_base0>> m_registry;
};
Than we define a small type to combine a type and a numerical index for referencing arguments:
typedef std::pair<std::type_index, size_t> argument_index;
// helper function for creating an argument_index
template <class T>
argument_index arg(size_t idx)
{
return{ typeid(T), idx };
}
Finally, we need some template recursion to go through all expected arguments of a function, check if the user passed an argument of matching type and query it from the registry:
// helper trait for call function; called when there are unhandled arguments left
template <bool Done>
struct call_helper
{
template <class FuncRet, class ArgTuple, size_t N, class F, class... ExpandedArgs>
static FuncRet call(F func, const argument_registry& registry, const std::vector<argument_index>& args, ExpandedArgs&&... expanded_args)
{
// check if there are any arguments left in the passed vector
if (N == args.size())
{
throw std::invalid_argument("not enough arguments");
}
// get the type of the Nth argument
typedef typename std::tuple_element<N, ArgTuple>::type arg_type;
// check if the type matches the argument_index from our vector
if (std::type_index{ typeid(arg_type) } != args[N].first)
{
throw std::invalid_argument("argument of wrong type");
}
// query the argument from the registry
auto& arg = registry.get_argument<arg_type>(args[N].second);
// add the argument to the ExpandedArgs pack and continue the recursion with the next argument N + 1
return call_helper<std::tuple_size<ArgTuple>::value == N + 1>::template call<FuncRet, ArgTuple, N + 1>(func, registry, args, std::forward<ExpandedArgs>(expanded_args)..., arg);
}
};
// helper trait for call function; called when there are no arguments left
template <>
struct call_helper<true>
{
template <class FuncRet, class ArgTuple, size_t N, class F, class... ExpandedArgs>
static FuncRet call(F func, const argument_registry&, const std::vector<argument_index>& args, ExpandedArgs&&... expanded_args)
{
if (N != args.size())
{
// unexpected arguments in the vector
throw std::invalid_argument("too many arguments");
}
// call the function with all the expanded arguments
return func(std::forward<ExpandedArgs>(expanded_args)...);
}
};
// call function can only work on "real", plain functions
// as you could never do dynamic overload resolution in C++
template <class Ret, class... Args>
Ret call(Ret(*func)(Args...), const argument_registry& registry, const std::vector<argument_index>& args)
{
// put the argument types into a tuple for easier handling
typedef std::tuple<Args...> arg_tuple;
// start the call_helper recursion
return call_helper<sizeof...(Args) == 0>::template call<Ret, arg_tuple, 0>(func, registry, args);
}
Now you can use it like this:
int foo(int i, const double& d, const char* str)
{
printf("called foo with %d, %f, %s", i, d, str);
// return something
return 0;
}
int main()
{
// prepare some arguments
std::vector<int> ints = { 1, 2, 3 };
std::vector<double> doubles = { 10., 20., 30. };
std::vector<const char*> str = { "alpha", "bravo", "charlie" };
// register them
argument_registry registry;
registry.register_range<int>(ints.begin(), ints.end());
registry.register_range<double>(doubles.begin(), doubles.end());
registry.register_range<const char*>(str.begin(), str.end());
// call function foo with arguments from the registry
return call(foo, registry, {arg<int>(2), arg<double>(0), arg<const char*>(1)});
}
Live example: http://coliru.stacked-crooked.com/a/7350319f88d86c53
This design should be open for any argument type without the need to list all the supported types somewhere.
As noted in the code comments, you cannot call any callable object like this in general, because overload resolution could never be done at runtime in C++.
Instead of clarifying the question, as I requested, you have put it up for bounty. Except if that really is the question, i.e. a homework assignment with no use case, just exercising you on general basic programming, except for that only sheer luck will then give you an answer to your real question: people have to guess about what the problem to be solved, is. That's the reason why nobody's bothered, even with the bounty, to present a solution to the when-obvious-errors-are-corrected exceedingly trivial question that you literally pose, namely how to do exactly this:
vector<int> ints;
vector<double> doubles;
struct Arg {
enum Type {
Int,
Double
};
Type type;
int index;
};
template <typename F>
void Call(const F& f, const vector<Arg>& args) {
// TODO:
// - First assert that count and types or arguments of <f> agree with <args>.
// - Call "f(args)"
}
// Example:
void copy(int a, double& b) {
b = a;
}
int test() {
Call(copy, {{Int, 3}, {Double, 2}}); // copy(ints[3], double[2]);
}
In C++11 and later one very direct way is this:
#include <assert.h>
#include <vector>
using std::vector;
namespace g {
vector<int> ints;
vector<double> doubles;
}
struct Arg {
enum Type {
Int,
Double
};
Type type;
int index;
};
template <typename F>
void Call(const F& f, const vector<Arg>& args)
{
// Was TODO:
// - First assert that count and types or arguments of <f> agree with <args>.
assert( args.size() == 2 );
assert( args[0].type == Arg::Int );
assert( int( g::ints.size() ) > args[0].index );
assert( args[1].type == Arg::Double );
assert( int( g::doubles.size() ) > args[1].index );
// - Call "f(args)"
f( g::ints[args[0].index], g::doubles[args[1].index] );
}
// Example:
void copy(int a, double& b)
{
b = a;
}
auto test()
{
Call(copy, {{Arg::Int, 3}, {Arg::Double, 2}}); // copy(ints[3], double[2]);
}
namespace h {}
auto main()
-> int
{
g::ints = {000, 100, 200, 300};
g::doubles = {1.62, 2.72, 3.14};
test();
assert( g::doubles[2] == 300 );
}
There are no particularly relevant new features in C++14.
I propose this answer following my comment on your question. Seeing that in the requirements, you stated:
Preferably we should not be required to create a struct that
enumerates all the types we want to support.
It could suggests you would like to get rid of the type enumerator in your Arg structure. Then, only the value would be left: then why not using plain C++ types directly, instead of wrapping them ?
It assumes you then know all your argument types at compile time
(This assumption could be very wrong, but I did not see any requirement in your question preventing it. I would be glad to rewrite my answer if you give more details).
The C++11 variadic template solution
Now to the solution, using C++11 variadic templates and perfect forwarding. In a file Call.h:
template <class F, class... T_Args>
void Call(F f, T_Args &&... args)
{
f(std::forward<T_Args>(args)...);
}
Solution properties
This approach seems to satisfy all your explicit requirements:
Works with C++11 standard
Checks that count and types or arguments of f agress with args.
It actually does that early, at compile time, instead of a possible runtime approach.
No need to manually enumerate the accepted types (actually works with any C++ type, be it native or user defined)
Not in your requirement, but nice to have:
Very compact, because it leverage a native features introduced in C++11.
Accepts any number of arguments
The type of the argument and the type of the corresponding f parameter do not have to match exactly, but have to be compatible (exactly like a plain C++ function call).
Example usage
You could test it in a simple main.cpp file:
#include "Call.h"
#include <iostream>
void copy(int a, double& b)
{
b = a;
}
void main()
{
int a = 5;
double b = 6.2;
std::cout << "b before: " << b << std::endl;
Call(copy, a, b);
std::cout << "b now: " << b << std::endl;
}
Which would print:
b before: 6.2
b now: 5
I am a little confused about how can I read each argument from the tuple by using variadic templates.
Consider this function:
template<class...A> int func(A...args){
int size = sizeof...(A);
.... }
I call it from the main file like:
func(1,10,100,1000);
Now, I don't know how I have to extend the body of func to be able to read each argument separately so that I can, for example, store the arguments in an array.
You have to provide overrides for the functions for consuming the first N (usually one) arguments.
void foo() {
// end condition argument pack is empty
}
template <class First, class... Rest>
void foo(First first, Rest... rest) {
// Do something with first
cout << first << endl;
foo(rest...); // Unpack the arguments for further treatment
}
When you unpack the variadic parameter it finds the next overload.
Example:
foo(42, true, 'a', "hello");
// Calls foo with First = int, and Rest = { bool, char, char* }
// foo(42, Rest = {true, 'a', "hello"}); // not the real syntax
Then next level down we expand the previous Rest and get:
foo(true, Rest = { 'a', "hello"}); // First = bool
And so on until Rest contains no members in which case unpacking it calls foo() (the overload with no arguments).
Storing the pack if different types
If you want to store the entire argument pack you can use an std::tuple
template <class... Pack>
void store_pack(Pack... p) {
std::tuple<Pack...> store( p... );
// do something with store
}
However this seems less useful.
Storing the pack if it's homogeneous
If all the values in the pack are the same type you can store them all like this:
vector<int> reverse(int i) {
vector<int> ret;
ret.push_back(i);
return ret;
}
template <class... R>
vector<int> reverse(int i, R... r) {
vector<int> ret = reverse(r...);
ret.push_back(i);
return ret;
}
int main() {
auto v = reverse(1, 2, 3, 4);
for_each(v.cbegin(), v.cend(),
[](int i ) {
std::cout << i << std::endl;
}
);
}
However this seems even less useful.
If the arguments are all of the same type, you could store the arguments in an array like this (using the type of the first argument for the array):
template <class T, class ...Args>
void foo(const T& first, const Args&... args)
{
T arr[sizeof...(args) + 1] = { first, args...};
}
int main()
{
foo(1);
foo(1, 10, 100, 1000);
}
If the types are different, I suppose you could use boost::any but then I don't see how you are going to find out outside of the given template, which item is of which type (how you are going to use the stored values).
Edit:
If the arguments are all of the same type and you want to store them into a STL container, you could rather use the std::initializer_list<T>. For example, Motti's example of storing values in reverse:
#include <vector>
#include <iostream>
#include <iterator>
template <class Iter>
std::reverse_iterator<Iter> make_reverse_iterator(Iter it)
{
return std::reverse_iterator<Iter>(it);
}
template <class T>
std::vector<T> reverse(std::initializer_list<T> const & init)
{
return std::vector<T>(make_reverse_iterator(init.end()), make_reverse_iterator(init.begin()));
}
int main() {
auto v = reverse({1, 2, 3, 4});
for (auto it = v.begin(); it != v.end(); ++it) {
std::cout << *it << std::endl;
}
}
For sticking into an array if the arguments have different types, you can use also std::common_type<>
template<class ...A> void func(A ...args){
typedef typename std::common_type<A...>::type common;
std::array<common, sizeof...(A)> a = {{ args... }};
}
So for example, func(std::string("Hello"), "folks") creates an array of std::string.
If you need to store arguments in the array you could use array of boost::any as follows:
template<typename... A> int func(const A&... args)
{
boost::any arr[sizeof...(A)] = { args... };
return 0;
}
I am new to C++11. I am writing the following recursive lambda function, but it doesn't compile.
sum.cpp
#include <iostream>
#include <functional>
auto term = [](int a)->int {
return a*a;
};
auto next = [](int a)->int {
return ++a;
};
auto sum = [term,next,&sum](int a, int b)mutable ->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
int main(){
std::cout<<sum(1,10)<<std::endl;
return 0;
}
compilation error:
vimal#linux-718q:~/Study/09C++/c++0x/lambda> g++ -std=c++0x sum.cpp
sum.cpp: In lambda function:
sum.cpp:18:36: error: ‘((<lambda(int, int)>*)this)-><lambda(int, int)>::sum’ cannot be used as a function
gcc version
gcc version 4.5.0 20091231 (experimental) (GCC)
But if I change the declaration of sum() as below, it works:
std::function<int(int,int)> sum = [term,next,&sum](int a, int b)->int {
if(a>b)
return 0;
else
return term(a) + sum(next(a),b);
};
Could someone please throw light on this?
Think about the difference between the auto version and the fully specified type version. The auto keyword infers its type from whatever it's initialized with, but what you're initializing it with needs to know what its type is (in this case, the lambda closure needs to know the types it's capturing). Something of a chicken-and-egg problem.
On the other hand, a fully specified function object's type doesn't need to "know" anything about what is being assigned to it, and so the lambda's closure can likewise be fully informed about the types its capturing.
Consider this slight modification of your code and it may make more sense:
std::function<int(int, int)> sum;
sum = [term, next, &sum](int a, int b) -> int {
if (a > b)
return 0;
else
return term(a) + sum(next(a), b);
};
Obviously, this wouldn't work with auto. Recursive lambda functions work perfectly well (at least they do in MSVC, where I have experience with them), it's just that they aren't really compatible with type inference.
The trick is to feed in the lambda implementation to itself as a parameter, not by capture.
const auto sum = [term, next](int a, int b) {
auto sum_impl = [term, next](int a, int b, auto& sum_ref) mutable {
if (a > b) {
return 0;
}
return term(a) + sum_ref(next(a), b, sum_ref);
};
return sum_impl(a, b, sum_impl);
};
All problems in computer science can be solved by another level of indirection. I first found this easy trick at http://pedromelendez.com/blog/2015/07/16/recursive-lambdas-in-c14/
It does require C++14 while the question is on C++11, but perhaps interesting to most.
Here's the full example at Godbolt.
Going via std::function is also possible but can result in slower code. But not always. Have a look at the answers to std::function vs template
This is not just a peculiarity about C++,
it's directly mapping to the mathematics of lambda calculus. From Wikipedia:
Lambda calculus cannot express this as directly as some other
notations:
all functions are anonymous in lambda calculus, so we can't refer to a
value which is yet to be defined, inside the lambda term defining that
same value. However, recursion can still be achieved by arranging for a
lambda expression to receive itself as its argument value
With C++14, it is now quite easy to make an efficient recursive lambda without having to incur the additional overhead of std::function, in just a few lines of code:
template <class F>
struct y_combinator {
F f; // the lambda will be stored here
// a forwarding operator():
template <class... Args>
decltype(auto) operator()(Args&&... args) const {
// we pass ourselves to f, then the arguments.
return f(*this, std::forward<Args>(args)...);
}
};
// helper function that deduces the type of the lambda:
template <class F>
y_combinator<std::decay_t<F>> make_y_combinator(F&& f) {
return {std::forward<F>(f)};
}
with which your original sum attempt becomes:
auto sum = make_y_combinator([term,next](auto sum, int a, int b) -> int {
if (a>b) {
return 0;
}
else {
return term(a) + sum(next(a),b);
}
});
In C++17, with CTAD, we can add a deduction guide:
template <class F> y_combinator(F) -> y_combinator<F>;
Which obviates the need for the helper function. We can just write y_combinator{[](auto self, ...){...}} directly.
In C++20, with CTAD for aggregates, the deduction guide won't be necessary.
In C++23, with deducing this, you don't need a Y-combinator at all:
auto sum = [term,next](this auto const& sum, int a, int b) -> int {
if (a>b) {
return 0;
}
else {
return term(a) + sum(next(a),b);
}
}
I have another solution, but work only with stateless lambdas:
void f()
{
static int (*self)(int) = [](int i)->int { return i>0 ? self(i-1)*i : 1; };
std::cout<<self(10);
}
Trick here is that lambdas can access static variables and you can convert stateless ones to function pointer.
You can use it with standard lambdas:
void g()
{
int sum;
auto rec = [&sum](int i) -> int
{
static int (*inner)(int&, int) = [](int& _sum, int i)->int
{
_sum += i;
return i>0 ? inner(_sum, i-1)*i : 1;
};
return inner(sum, i);
};
}
Its work in GCC 4.7
To make lambda recursive without using external classes and functions (like std::function or fixed-point combinator) one can use the following construction in C++14 (live example):
#include <utility>
#include <list>
#include <memory>
#include <iostream>
int main()
{
struct tree
{
int payload;
std::list< tree > children = {}; // std::list of incomplete type is allowed
};
std::size_t indent = 0;
// indication of result type here is essential
const auto print = [&] (const auto & self, const tree & node) -> void
{
std::cout << std::string(indent, ' ') << node.payload << '\n';
++indent;
for (const tree & t : node.children) {
self(self, t);
}
--indent;
};
print(print, {1, {{2, {{8}}}, {3, {{5, {{7}}}, {6}}}, {4}}});
}
prints:
1
2
8
3
5
7
6
4
Note, result type of lambda should be specified explicitly.
You can make a lambda function call itself recursively. The only thing you need to do is to is to reference it through a function wrapper so that the compiler knows it's return and argument type (you can't capture a variable -- the lambda itself -- that hasn't been defined yet).
function<int (int)> f;
f = [&f](int x) {
if (x == 0) return 0;
return x + f(x-1);
};
printf("%d\n", f(10));
Be very careful not to run out of the scope of the wrapper f.
I ran a benchmark comparing a recursive function vs a recursive lambda function using the std::function<> capture method. With full optimizations enabled on clang version 4.1, the lambda version ran significantly slower.
#include <iostream>
#include <functional>
#include <chrono>
uint64_t sum1(int n) {
return (n <= 1) ? 1 : n + sum1(n - 1);
}
std::function<uint64_t(int)> sum2 = [&] (int n) {
return (n <= 1) ? 1 : n + sum2(n - 1);
};
auto const ITERATIONS = 10000;
auto const DEPTH = 100000;
template <class Func, class Input>
void benchmark(Func&& func, Input&& input) {
auto t1 = std::chrono::high_resolution_clock::now();
for (auto i = 0; i != ITERATIONS; ++i) {
func(input);
}
auto t2 = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2-t1).count();
std::cout << "Duration: " << duration << std::endl;
}
int main() {
benchmark(sum1, DEPTH);
benchmark(sum2, DEPTH);
}
Produces results:
Duration: 0 // regular function
Duration: 4027 // lambda function
(Note: I also confirmed with a version that took the inputs from cin, so as to eliminate compile time evaluation)
Clang also produces a compiler warning:
main.cc:10:29: warning: variable 'sum2' is uninitialized when used within its own initialization [-Wuninitialized]
Which is expected, and safe, but should be noted.
It's great to have a solution in our toolbelts, but I think the language will need a better way to handle this case if performance is to be comparable to current methods.
Note:
As a commenter pointed out, it seems latest version of VC++ has found a way to optimize this to the point of equal performance. Maybe we don't need a better way to handle this, after all (except for syntactic sugar).
Also, as some other SO posts have outlined in recent weeks, the performance of std::function<> itself may be the cause of slowdown vs calling function directly, at least when the lambda capture is too large to fit into some library-optimized space std::function uses for small-functors (I guess kinda like the various short string optimizations?).
Here is a refined version of the Y-combinator solution based on one proposed by #Barry.
template <class F>
struct recursive {
F f;
template <class... Ts>
decltype(auto) operator()(Ts&&... ts) const { return f(std::ref(*this), std::forward<Ts>(ts)...); }
template <class... Ts>
decltype(auto) operator()(Ts&&... ts) { return f(std::ref(*this), std::forward<Ts>(ts)...); }
};
template <class F> recursive(F) -> recursive<F>;
auto const rec = [](auto f){ return recursive{std::move(f)}; };
To use this, one could do the following
auto fib = rec([&](auto&& fib, int i) {
// implementation detail omitted.
});
It is similar to the let rec keyword in OCaml, although not the same.
In C++23 deducing this (P0847) will be added:
auto f = [](this auto& self, int i) -> int
{
return i > 0 ? self(i - 1) + i : 0;
}
For now its only available in EDG eccp and (partially) available in MSVC:
https://godbolt.org/z/f3E3xT3fY
This is a slightly simpler implementation of the fixpoint operator which makes it a little more obvious exactly what's going on.
#include <iostream>
#include <functional>
using namespace std;
template<typename T, typename... Args>
struct fixpoint
{
typedef function<T(Args...)> effective_type;
typedef function<T(const effective_type&, Args...)> function_type;
function_type f_nonr;
T operator()(Args... args) const
{
return f_nonr(*this, args...);
}
fixpoint(const function_type& p_f)
: f_nonr(p_f)
{
}
};
int main()
{
auto fib_nonr = [](const function<int(int)>& f, int n) -> int
{
return n < 2 ? n : f(n-1) + f(n-2);
};
auto fib = fixpoint<int,int>(fib_nonr);
for (int i = 0; i < 6; ++i)
{
cout << fib(i) << '\n';
}
}
C++ 14:
Here is a recursive anonymous stateless/no capture generic set of lambdas
that outputs all numbers from 1, 20
([](auto f, auto n, auto m) {
f(f, n, m);
})(
[](auto f, auto n, auto m) -> void
{
cout << typeid(n).name() << el;
cout << n << el;
if (n<m)
f(f, ++n, m);
},
1, 20);
If I understand correctly this is using the Y-combinator solution
And here is the sum(n, m) version
auto sum = [](auto n, auto m) {
return ([](auto f, auto n, auto m) {
int res = f(f, n, m);
return res;
})(
[](auto f, auto n, auto m) -> int
{
if (n > m)
return 0;
else {
int sum = n + f(f, n + 1, m);
return sum;
}
},
n, m); };
auto result = sum(1, 10); //result == 55
Here's the proof that a recursive lambda with a small body almost has the same performance like a usual recursive fuction which can call itself directly.
#include <iostream>
#include <chrono>
#include <type_traits>
#include <functional>
#include <atomic>
#include <cmath>
using namespace std;
using namespace chrono;
unsigned recursiveFn( unsigned x )
{
if( x ) [[likely]]
return recursiveFn( x - 1 ) + recursiveFn( x - 1 );
else
return 0;
};
atomic_uint result;
int main()
{
auto perf = []( function<void ()> fn ) -> double
{
using dur_t = high_resolution_clock::duration;
using urep_t = make_unsigned_t<dur_t::rep>;
high_resolution_clock::duration durMin( (urep_t)-1 >> 1 );
for( unsigned r = 10; r--; )
{
auto start = high_resolution_clock::now();
fn();
dur_t dur = high_resolution_clock::now() - start;
if( dur < durMin )
durMin = dur;
}
return durMin.count() / 1.0e9;
};
auto recursiveLamdba = []( auto &self, unsigned x ) -> unsigned
{
if( x ) [[likely]]
return self( self, x - 1 ) + self( self, x - 1 );
else
return 0;
};
constexpr unsigned DEPTH = 28;
double
tLambda = perf( [&]() { ::result = recursiveLamdba( recursiveLamdba, DEPTH ); } ),
tFn = perf( [&]() { ::result = recursiveFn( DEPTH ); } );
cout << trunc( 1000.0 * (tLambda / tFn - 1.0) + 0.5 ) / 10.0 << "%" << endl;
}
For my AMD Zen1 CPU with current MSVC the recursiveFn is about 10% faster. For my Phenom II x4 945 with g++ 11.1.x both functions have the same performance.
Keep in mind that this is almost the worst case since the body of the funtion is very small. If it is larger the part of the recursive function call itself is smaller.
You're trying to capture a variable (sum) you're in the middle of defining. That can't be good.
I don't think truely self-recursive C++0x lambdas are possible. You should be able to capture other lambdas, though.
Here is the final answer for the OP. Anyway, Visual Studio 2010 does not support capturing global variables. And you do not need to capture them because global variable is accessable globally by define. The following answer uses local variable instead.
#include <functional>
#include <iostream>
template<typename T>
struct t2t
{
typedef T t;
};
template<typename R, typename V1, typename V2>
struct fixpoint
{
typedef std::function<R (V1, V2)> func_t;
typedef std::function<func_t (func_t)> tfunc_t;
typedef std::function<func_t (tfunc_t)> yfunc_t;
class loopfunc_t {
public:
func_t operator()(loopfunc_t v)const {
return func(v);
}
template<typename L>
loopfunc_t(const L &l):func(l){}
typedef V1 Parameter1_t;
typedef V2 Parameter2_t;
private:
std::function<func_t (loopfunc_t)> func;
};
static yfunc_t fix;
};
template<typename R, typename V1, typename V2>
typename fixpoint<R, V1, V2>::yfunc_t fixpoint<R, V1, V2>::fix = [](tfunc_t f) -> func_t {
return [f](fixpoint<R, V1, V2>::loopfunc_t x){ return f(x(x)); }
([f](fixpoint<R, V1, V2>::loopfunc_t x) -> fixpoint<R, V1, V2>::func_t{
auto &ff = f;
return [ff, x](t2t<decltype(x)>::t::Parameter1_t v1,
t2t<decltype(x)>::t::Parameter1_t v2){
return ff(x(x))(v1, v2);
};
});
};
int _tmain(int argc, _TCHAR* argv[])
{
auto term = [](int a)->int {
return a*a;
};
auto next = [](int a)->int {
return ++a;
};
auto sum = fixpoint<int, int, int>::fix(
[term,next](std::function<int (int, int)> sum1) -> std::function<int (int, int)>{
auto &term1 = term;
auto &next1 = next;
return [term1, next1, sum1](int a, int b)mutable ->int {
if(a>b)
return 0;
else
return term1(a) + sum1(next1(a),b);
};
});
std::cout<<sum(1,10)<<std::endl; //385
return 0;
}
This answer is inferior to Yankes' one, but still, here it goes:
using dp_type = void (*)();
using fp_type = void (*)(dp_type, unsigned, unsigned);
fp_type fp = [](dp_type dp, unsigned const a, unsigned const b) {
::std::cout << a << ::std::endl;
return reinterpret_cast<fp_type>(dp)(dp, b, a + b);
};
fp(reinterpret_cast<dp_type>(fp), 0, 1);
You need a fixed point combinator. See this.
or look at the following code:
//As decltype(variable)::member_name is invalid currently,
//the following template is a workaround.
//Usage: t2t<decltype(variable)>::t::member_name
template<typename T>
struct t2t
{
typedef T t;
};
template<typename R, typename V>
struct fixpoint
{
typedef std::function<R (V)> func_t;
typedef std::function<func_t (func_t)> tfunc_t;
typedef std::function<func_t (tfunc_t)> yfunc_t;
class loopfunc_t {
public:
func_t operator()(loopfunc_t v)const {
return func(v);
}
template<typename L>
loopfunc_t(const L &l):func(l){}
typedef V Parameter_t;
private:
std::function<func_t (loopfunc_t)> func;
};
static yfunc_t fix;
};
template<typename R, typename V>
typename fixpoint<R, V>::yfunc_t fixpoint<R, V>::fix =
[](fixpoint<R, V>::tfunc_t f) -> fixpoint<R, V>::func_t {
fixpoint<R, V>::loopfunc_t l = [f](fixpoint<R, V>::loopfunc_t x) ->
fixpoint<R, V>::func_t{
//f cannot be captured since it is not a local variable
//of this scope. We need a new reference to it.
auto &ff = f;
//We need struct t2t because template parameter
//V is not accessable in this level.
return [ff, x](t2t<decltype(x)>::t::Parameter_t v){
return ff(x(x))(v);
};
};
return l(l);
};
int _tmain(int argc, _TCHAR* argv[])
{
int v = 0;
std::function<int (int)> fac =
fixpoint<int, int>::fix([](std::function<int (int)> f)
-> std::function<int (int)>{
return [f](int i) -> int{
if(i==0) return 1;
else return i * f(i-1);
};
});
int i = fac(10);
std::cout << i; //3628800
return 0;
}