How would I 'generate variadic parameters'? - c++

I need a way to pass a variable amount of parameters to a function in this circumstance:
template<typename ...T>
struct Lunch
{
Lunch(T...){}
};
template<typename T>
T CheckLuaValue(lua_State* luaState,int index)
{
//Do Stuff
return value;
}
template <class MemberType, typename ReturnType, typename... Params>
struct MemberFunctionWrapper <ReturnType (MemberType::*) (Params...)>
{
static int CFunctionWrapper (lua_State* luaState)
{
ReturnType (MemberType::*)(Params...) functionPointer = GetFunctionPointer();
MemberType* member = GetMemberPointer();
int index = 1;
//Get a value for each type in Params
Lunch<Params...>
{
(CheckLuaValue<Params>(luaState,index), index++, void(), 0)...
};
CheckLuaValue returns a value for each type in Params. My problem is that I now need a way to call my function with all of those values
member->*functionPointer(returnedLuaValues);
}
};
How would I go about doing this?

So I stole some of Luc Danton's sequence advice to sFuller and Pubby (about sequences), and I generated this "stop messing around with operator," version:
#include <iostream>
struct lua_State {};
template<typename T>
T CheckLuaValue( int n, lua_State* l)
{
std::cout << "arg[" << n << "] gotten\n";
return T(n);
}
template<int ...>
struct seq { };
// generates a seq< First, ..., Last-1 > as "type"
template<int First, int Last>
struct gen_seq
{
template<int N, int... S>
struct helper : helper<N-1, N-1, S...> {};
template<int... S>
struct helper<First, S...> {
typedef seq<S...> type;
};
typedef typename helper<Last>::type type;
};
template< typename X >
struct MemberFunctionWrapper;
template< typename F >
struct MemberFunctionHelper
{
typedef F MethodPtr;
};
template<class InstanceType, typename ReturnType, typename... Params>
struct MemberFunctionWrapper< ReturnType(InstanceType::*)(Params...) >
{
typedef MemberFunctionHelper<ReturnType(InstanceType::*)(Params...)> Helper;
typedef typename Helper::MethodPtr MethodPtr;
static MethodPtr& GetFunctionPointer() {static MethodPtr pFunc; return pFunc;}
static InstanceType*& GetMemberPointer() {static InstanceType* pThis;return pThis;}
template<int n, typename Param>
static auto GetLuaValue( lua_State* luaState )->decltype(CheckLuaValue<Param>(n,luaState))
{
return CheckLuaValue<Param>(n,luaState);
}
template< typename sequence >
struct call;
template< int... I >
struct call<seq<I...>>
{
ReturnType operator()( lua_State* luaState, InstanceType* instance, MethodPtr method ) const
{
return (instance->*method)( GetLuaValue<I,Params>( luaState )... );
}
};
static int CFunctionWrapper( lua_State* luaState)
{
MethodPtr func = GetFunctionPointer();
InstanceType* instance = GetMemberPointer();
ReturnType retval = call< typename gen_seq< 1, sizeof...(Params)+1 >::type >()( luaState, instance, func );
return 0;
}
};
struct test{ int foo(int x, double d){std::cout << "x:" << x << " d:" << d << "\n";}};
int main(){
typedef MemberFunctionWrapper< int(test::*)(int, double) > wrapper;
test bar;
wrapper::GetFunctionPointer() = &test::foo;
wrapper::GetMemberPointer() = &bar;
wrapper::CFunctionWrapper(0);
}
now, note that the calls to CheckLuaValue can be out of order (ie, it can ask for arg 2 from Lua before arg 1), but the right one will be passed to the right argument.
Here is a test run: http://ideone.com/XVmQQ6

If I understand correctly, you should change the definition Lunch to invoke the member function pointer:
template <class MemberType, typename ReturnType, typename... Params>
struct MemberFunctionWrapper <ReturnType (MemberType::*) (Params...)>
{
template<typename ...T>
struct foo // new Lunch
{
foo(ReturnType (MemberType::*)(Params...) functionPointer, MemberType* member, T... args){
member->*functionPointer(args...);
}
};
static int CFunctionWrapper (lua_State* luaState)
{
ReturnType (MemberType::*)(Params...) functionPointer = GetFunctionPointer();
MemberType* member = GetMemberPointer();
int index = 1;
//member->*(bindedMemberFunction->memberFunction);
//Get a value for each type in Params
foo<Params...>
{
functionPointer,
member,
(++index, CheckLuaValue<Params>(luaState,index))...
};
}
};

Related

Unpack Data for Variadic Template Function Calls stored as Array (Goal:RPC)

The idea is to create the following functionality (Looks easy)
void test(int , float , char* ){ /*gets called*/ }
void main()
{
RegisterRPC( test , int , float , char* )
}
Pseudo-code to register the function:
std::map<std::string , std::function<void()> > functionarray;
template<typename F, typename... Args>
void RegisterRPC( F , Args )
{
// somehow add to functionarray
}
Then, when data comes from Network, the data needs to be decomposed to call test with the proper args.
ProcessData(data)
{
data.begin();
functionarray[data.get<char*>()] (
data.get<int>() ,
data.get<float>() ,
data.get<char*>() ); // the RegisterRPC parameters
}
I already found that Variadic Templates can store args
expanded parameter list for variadic template
And it can decopose args into classes
How can I iterate over a packed variadic template argument list?
So I believe its possible - just I dont get how..
Hope somebody can help.
Edit : In case somebody is interested in the complete solution :
#include <tuple>
#include <iostream>
#include <strstream>
#include <istream>
#include <sstream>
#include <string>
// ------------- UTILITY---------------
template<int...> struct index_tuple{};
template<int I, typename IndexTuple, typename... Types>
struct make_indexes_impl;
template<int I, int... Indexes, typename T, typename ... Types>
struct make_indexes_impl<I, index_tuple<Indexes...>, T, Types...>
{
typedef typename make_indexes_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type;
};
template<int I, int... Indexes>
struct make_indexes_impl<I, index_tuple<Indexes...> >
{
typedef index_tuple<Indexes...> type;
};
template<typename ... Types>
struct make_indexes : make_indexes_impl<0, index_tuple<>, Types...>
{};
// ----------UNPACK TUPLE AND APPLY TO FUNCTION ---------
using namespace std;
template<class Ret, class... Args, int... Indexes >
Ret apply_helper(Ret(*pf)(Args...), index_tuple< Indexes... >, tuple<Args...>&& tup)
{
return pf(forward<Args>(get<Indexes>(tup))...);
}
template<class Ret, class ... Args>
Ret apply(Ret(*pf)(Args...), const tuple<Args...>& tup)
{
return apply_helper(pf, typename make_indexes<Args...>::type(), tuple<Args...>(tup));
}
template<class Ret, class ... Args>
Ret apply(Ret(*pf)(Args...), tuple<Args...>&& tup)
{
return apply_helper(pf, typename make_indexes<Args...>::type(), forward<tuple<Args...>>(tup));
}
// --- make tuple ---
template <typename T> T read(std::istream& is)
{
T t; is >> t; cout << t << endl; return t;
}
template <typename... Args>
std::tuple<Args...> parse(std::istream& is)
{
return std::make_tuple(read<Args>(is)...);
}
template <typename... Args>
std::tuple<Args...> parse(const std::string& str)
{
std::istringstream ips(str);
return parse<Args...>(ips);
};
// ---- RPC stuff
class DataSource
{
std::string data;
public:
DataSource(std::string s) { data = s; };
template<class...Ts> std::tuple<Ts...> get() { return parse<Ts...>(data); };
};
std::map<std::string, std::function<void(DataSource*)> > functionarray;
template<typename... Args, class F>
void RegisterRPC(std::string name, F f) {
functionarray[name] = [f](DataSource* data){apply(f, data->get<Args...>()); };
}
// --------------------- TEST ------------------
void one(int i, double d, string s)
{
std::cout << "function one(" << i << ", " << d << ", " << s << ");\n";
}
int main()
{
RegisterRPC<int, double, string>("test1", one);
DataSource* data=new DataSource("5 2 huhu");
functionarray["test1"](data);
system("pause");
return 0;
}
// --------------------- TEST ------------------
First, write a "call with tuple". This takes a callable object f and a tuple t, and calls f( std::get<0>(t), std::get<1>(t), ... ).
here is one of many such implementations on stack overflow. You can write a better one in C++14, or wait for it to arrive in C++1z.
Second, write data.get<std::tuple<A,B,C,...>>() that returns a tuple of type A,B,C,.... This is easy:
template<class...Ts>
std::tuple<Ts...> DataSource::get() {
return std::tuple<Ts...>{get<Ts>()...}; // some compilers get order here wrong, test!
}
now our function array looks like this:
std::map<std::string , std::function<void(DataSource*)> > functionarray;
template<class...Args, class F>
std::function<void(DataSource*)> from_source( F f ) {
// `[f = std::move(f)]` is C++14. In C++11, just do `[f]` instead
return [f = std::move(f)](DataSource* data){
call_from_tuple( f, data->get<std::tuple<Args...>>() );
};
}
template<typename... Args, class F>
void RegisterRPC( F f ) {
functionarray.push_back( from_source<Args...>( std::move(f) ) );
}
and end use is:
void test(int , float , char* ){ /*gets called*/ }
void main()
{
RegisterRPC<int,float,char*>( test )
}
I recomment against using char*. I'd use std::string, or std::vector<char> or even std::unique_ptr<char[]>, so lifetime is extremely clear.
The trick is that we erase at the point where we know the type information, which is where we wrap the function. There, we give it instructions on how to get the types from the data source and call itself, leaving behind a function of type "data source -> nothing".
We take "Ts... -> nothing" (your F) and "(DataSource -> Ts)..." (the stream of data over the network) and compose it into "DataSource -> nothing" (the std::function you store).

Switch statement variadic template expansion

Let me please consider the following synthetic example:
inline int fun2(int x) {
return x;
}
inline int fun2(double x) {
return 0;
}
inline int fun2(float x) {
return -1;
}
int fun(const std::tuple<int,double,float>& t, std::size_t i) {
switch(i) {
case 0: return fun2(std::get<0>(t));
case 1: return fun2(std::get<1>(t));
case 2: return fun2(std::get<2>(t));
}
}
The question is how should I expand this to the general case
template<class... Args> int fun(const std::tuple<Args...>& t, std::size_t i) {
// ?
}
Guaranteeing that
fun2 can be inlined into fun
search complexity not worse than O(log(i)) (for large i).
It is known that optimizer usually uses lookup jump table or compile-time binary search tree when large enough switch expanded. So, I would like to keep this property affecting performance for large number of items.
Update #3: I remeasured performance with uniform random index value:
1 10 20 100
#TartanLlama
gcc ~0 42.9235 44.7900 46.5233
clang 10.2046 38.7656 40.4316 41.7557
#chris-beck
gcc ~0 37.564 51.3653 81.552
clang ~0 38.0361 51.6968 83.7704
naive tail recursion
gcc 3.0798 40.6061 48.6744 118.171
clang 11.5907 40.6197 42.8172 137.066
manual switch statement
gcc 41.7236
clang 7.3768
Update #2: It seems that clang is able to inline functions in #TartanLlama solution whereas gcc always generates function call.
Ok, I rewrote my answer. This gives a different approach to what TartanLlama and also what I suggested before. This meets your complexity requirement and doesn't use function pointers so everything is inlineable.
Edit: Much thanks to Yakk for pointing out a quite significant optimization (for the compile-time template recursion depth required) in comments
Basically I make a binary tree of the types / function handlers using templates, and implement the binary search manually.
It might be possible to do this more cleanly using either mpl or boost::fusion, but this implementation is self-contained anyways.
It definitely meets your requirements, that the functions are inlineable and runtime look up is O(log n) in the number of types in the tuple.
Here's the complete listing:
#include <cassert>
#include <cstdint>
#include <tuple>
#include <iostream>
using std::size_t;
// Basic typelist object
template<typename... TL>
struct TypeList{
static const int size = sizeof...(TL);
};
// Metafunction Concat: Concatenate two typelists
template<typename L, typename R>
struct Concat;
template<typename... TL, typename... TR>
struct Concat <TypeList<TL...>, TypeList<TR...>> {
typedef TypeList<TL..., TR...> type;
};
template<typename L, typename R>
using Concat_t = typename Concat<L,R>::type;
// Metafunction First: Get first type from a typelist
template<typename T>
struct First;
template<typename T, typename... TL>
struct First <TypeList<T, TL...>> {
typedef T type;
};
template<typename T>
using First_t = typename First<T>::type;
// Metafunction Split: Split a typelist at a particular index
template<int i, typename TL>
struct Split;
template<int k, typename... TL>
struct Split<k, TypeList<TL...>> {
private:
typedef Split<k/2, TypeList<TL...>> FirstSplit;
typedef Split<k-k/2, typename FirstSplit::R> SecondSplit;
public:
typedef Concat_t<typename FirstSplit::L, typename SecondSplit::L> L;
typedef typename SecondSplit::R R;
};
template<typename T, typename... TL>
struct Split<0, TypeList<T, TL...>> {
typedef TypeList<> L;
typedef TypeList<T, TL...> R;
};
template<typename T, typename... TL>
struct Split<1, TypeList<T, TL...>> {
typedef TypeList<T> L;
typedef TypeList<TL...> R;
};
template<int k>
struct Split<k, TypeList<>> {
typedef TypeList<> L;
typedef TypeList<> R;
};
// Metafunction Subdivide: Split a typelist into two roughly equal typelists
template<typename TL>
struct Subdivide : Split<TL::size / 2, TL> {};
// Metafunction MakeTree: Make a tree from a typelist
template<typename T>
struct MakeTree;
/*
template<>
struct MakeTree<TypeList<>> {
typedef TypeList<> L;
typedef TypeList<> R;
static const int size = 0;
};*/
template<typename T>
struct MakeTree<TypeList<T>> {
typedef TypeList<> L;
typedef TypeList<T> R;
static const int size = R::size;
};
template<typename T1, typename T2, typename... TL>
struct MakeTree<TypeList<T1, T2, TL...>> {
private:
typedef TypeList<T1, T2, TL...> MyList;
typedef Subdivide<MyList> MySubdivide;
public:
typedef MakeTree<typename MySubdivide::L> L;
typedef MakeTree<typename MySubdivide::R> R;
static const int size = L::size + R::size;
};
// Typehandler: What our lists will be made of
template<typename T>
struct type_handler_helper {
typedef int result_type;
typedef T input_type;
typedef result_type (*func_ptr_type)(const input_type &);
};
template<typename T, typename type_handler_helper<T>::func_ptr_type me>
struct type_handler {
typedef type_handler_helper<T> base;
typedef typename base::func_ptr_type func_ptr_type;
typedef typename base::result_type result_type;
typedef typename base::input_type input_type;
static constexpr func_ptr_type my_func = me;
static result_type apply(const input_type & t) {
return me(t);
}
};
// Binary search implementation
template <typename T, bool b = (T::L::size != 0)>
struct apply_helper;
template <typename T>
struct apply_helper<T, false> {
template<typename V>
static int apply(const V & v, size_t index) {
assert(index == 0);
return First_t<typename T::R>::apply(v);
}
};
template <typename T>
struct apply_helper<T, true> {
template<typename V>
static int apply(const V & v, size_t index) {
if( index >= T::L::size ) {
return apply_helper<typename T::R>::apply(v, index - T::L::size);
} else {
return apply_helper<typename T::L>::apply(v, index);
}
}
};
// Original functions
inline int fun2(int x) {
return x;
}
inline int fun2(double x) {
return 0;
}
inline int fun2(float x) {
return -1;
}
// Adapted functions
typedef std::tuple<int, double, float> tup;
inline int g0(const tup & t) { return fun2(std::get<0>(t)); }
inline int g1(const tup & t) { return fun2(std::get<1>(t)); }
inline int g2(const tup & t) { return fun2(std::get<2>(t)); }
// Registry
typedef TypeList<
type_handler<tup, &g0>,
type_handler<tup, &g1>,
type_handler<tup, &g2>
> registry;
typedef MakeTree<registry> jump_table;
int apply(const tup & t, size_t index) {
return apply_helper<jump_table>::apply(t, index);
}
// Demo
int main() {
{
tup t{5, 1.5, 15.5f};
std::cout << apply(t, 0) << std::endl;
std::cout << apply(t, 1) << std::endl;
std::cout << apply(t, 2) << std::endl;
}
{
tup t{10, 1.5, 15.5f};
std::cout << apply(t, 0) << std::endl;
std::cout << apply(t, 1) << std::endl;
std::cout << apply(t, 2) << std::endl;
}
{
tup t{15, 1.5, 15.5f};
std::cout << apply(t, 0) << std::endl;
std::cout << apply(t, 1) << std::endl;
std::cout << apply(t, 2) << std::endl;
}
{
tup t{20, 1.5, 15.5f};
std::cout << apply(t, 0) << std::endl;
std::cout << apply(t, 1) << std::endl;
std::cout << apply(t, 2) << std::endl;
}
}
Live on Coliru:
http://coliru.stacked-crooked.com/a/3cfbd4d9ebd3bb3a
If you make fun2 into a class with overloaded operator():
struct fun2 {
inline int operator()(int x) {
return x;
}
inline int operator()(double x) {
return 0;
}
inline int operator()(float x) {
return -1;
}
};
then we can modify dyp's answer from here to work for us.
Note that this would look a lot neater in C++14, as we could have all the return types deduced and use std::index_sequence.
//call the function with the tuple element at the given index
template<class Ret, int N, class T, class Func>
auto apply_one(T&& p, Func func) -> Ret
{
return func( std::get<N>(std::forward<T>(p)) );
}
//call with runtime index
template<class Ret, class T, class Func, int... Is>
auto apply(T&& p, int index, Func func, seq<Is...>) -> Ret
{
using FT = Ret(T&&, Func);
//build up a constexpr array of function pointers to index
static constexpr FT* arr[] = { &apply_one<Ret, Is, T&&, Func>... };
//call the function pointer at the specified index
return arr[index](std::forward<T>(p), func);
}
//tag dispatcher
template<class Ret, class T, class Func>
auto apply(T&& p, int index, Func func) -> Ret
{
return apply<Ret>(std::forward<T>(p), index, func,
gen_seq<std::tuple_size<typename std::decay<T>::type>::value>{});
}
We then call apply and pass the return type as a template argument (you could deduce this using decltype or C++14):
auto t = std::make_tuple(1,1.0,1.0f);
std::cout << apply<int>(t, 0, fun2{}) << std::endl;
std::cout << apply<int>(t, 1, fun2{}) << std::endl;
std::cout << apply<int>(t, 2, fun2{}) << std::endl;
Live Demo
I'm not sure if this will completely fulfil your requirements due to the use of function pointers, but compilers can optimize this kind of thing pretty aggressively. The searching will be O(1) as the pointer array is just built once then indexed directly, which is pretty good. I'd try this out, measure, and see if it'll work for you.

Optimal way to access std::tuple element in runtime by index

I have function at designed to access std::tuple element by index specified in runtime
template<std::size_t _Index = 0, typename _Tuple, typename _Function>
inline typename std::enable_if<_Index == std::tuple_size<_Tuple>::value, void>::type
for_each(_Tuple &, _Function)
{}
template<std::size_t _Index = 0, typename _Tuple, typename _Function>
inline typename std::enable_if < _Index < std::tuple_size<_Tuple>::value, void>::type
for_each(_Tuple &t, _Function f)
{
f(std::get<_Index>(t));
for_each<_Index + 1, _Tuple, _Function>(t, f);
}
namespace detail { namespace at {
template < typename _Function >
struct helper
{
inline helper(size_t index_, _Function f_) : index(index_), f(f_), count(0) {}
template < typename _Arg >
void operator()(_Arg &arg_) const
{
if(index == count++)
f(arg_);
}
const size_t index;
mutable size_t count;
_Function f;
};
}} // end of namespace detail
template < typename _Tuple, typename _Function >
void at(_Tuple &t, size_t index_, _Function f)
{
if(std::tuple_size<_Tuple> ::value <= index_)
throw std::out_of_range("");
for_each(t, detail::at::helper<_Function>(index_, f));
}
It has linear complexity. How can i achive O(1) complexity?
Assuming you pass something similar to a generic lambda, i.e. a function object with an overloaded function call operator:
#include <iostream>
struct Func
{
template<class T>
void operator()(T p)
{
std::cout << __PRETTY_FUNCTION__ << " : " << p << "\n";
}
};
The you can build an array of function pointers:
#include <tuple>
template<int... Is> struct seq {};
template<int N, int... Is> struct gen_seq : gen_seq<N-1, N-1, Is...> {};
template<int... Is> struct gen_seq<0, Is...> : seq<Is...> {};
template<int N, class T, class F>
void apply_one(T& p, F func)
{
func( std::get<N>(p) );
}
template<class T, class F, int... Is>
void apply(T& p, int index, F func, seq<Is...>)
{
using FT = void(T&, F);
static constexpr FT* arr[] = { &apply_one<Is, T, F>... };
arr[index](p, func);
}
template<class T, class F>
void apply(T& p, int index, F func)
{
apply(p, index, func, gen_seq<std::tuple_size<T>::value>{});
}
Usage example:
int main()
{
std::tuple<int, double, char, double> t{1, 2.3, 4, 5.6};
for(int i = 0; i < 4; ++i) apply(t, i, Func{});
}
clang++ also accepts an expansion applied to a pattern that contains a lambda expression:
static FT* arr[] = { [](T& p, F func){ func(std::get<Is>(p)); }... };
(although I've to admit that looks really weird)
g++4.8.1 rejects this.

How do I make this template argument variadic?

Say I have a template declaration like this:
template <class A, class B, class C = A (&)(B)>
How would I make it so that I could have a variable amount of objects of type C? Doing class C ...c = x won't work because variadic template arguments can't have default values. So this is what I've tried:
template <typename T>
struct helper;
template <typename F, typename B>
struct helper<F(B)> {
typedef F (&type)(B);
};
template <class F, class B, typename helper<F(B)>::type ... C>
void f(C ...c) { // error
}
But up to the last part I get error messages. I don't think I'm doing this right. What am I doing wrong here?
I think you can use the following approach. First, some machinery for type traits. This allows you to determine if the types in an argument pack are homogeneous (I guess you want all functions to have the same signature):
struct null_type { };
// Declare primary template
template<typename... Ts>
struct homogeneous_type;
// Base step
template<typename T>
struct homogeneous_type<T>
{
using type = T;
static const bool isHomogeneous = true;
};
// Induction step
template<typename T, typename... Ts>
struct homogeneous_type<T, Ts...>
{
// The underlying type of the tail of the parameter pack
using type_of_remaining_parameters = typename
homogeneous_type<Ts...>::type;
// True if each parameter in the pack has the same type
static const bool isHomogeneous =
is_same<T, type_of_remaining_parameters>::value;
// If isHomogeneous is "false", the underlying type is a fictitious type
using type = typename conditional<isHomogeneous, T, null_type>::type;
};
// Meta-function to determine if a parameter pack is homogeneous
template<typename... Ts>
struct is_homogeneous_pack
{
static const bool value = homogeneous_type<Ts...>::isHomogeneous;
};
Then, some more type traits to figure out the signature of a generic function:
template<typename T>
struct signature;
template<typename A, typename B>
struct signature<A (&)(B)>
{
using ret_type = A;
using arg_type = B;
};
And finally, this is how you would define your variadic function template:
template <typename... F>
void foo(F&&... f)
{
static_assert(is_homogeneous_pack<F...>::value, "Not homogeneous!");
using fxn_type = typename homogeneous_type<F...>::type;
// This was template parameter A in your original code
using ret_type = typename signature<fxn_type>::ret_type;
// This was template parameter B in your original code
using arg_type = typename signature<fxn_type>::arg_type;
// ...
}
Here is a short test:
int fxn1(double) { }
int fxn2(double) { }
int fxn3(string) { }
int main()
{
foo(fxn1, fxn2); // OK
foo(fxn1, fxn2, fxn3); // ERROR! not homogeneous signatures
return 0;
}
Finally, if you need an inspiration on what to do once you have that argument pack, you can check out a small library I wrote (from which part of the machinery used in this answer is taken). An easy way to call all the functions in the argument pack F... f is the following (credits to #MarkGlisse):
initializer_list<int>{(f(forward<ArgType>(arg)), 0)...};
You can easily wrap that in a macro (just see Mark's answer to the link I posted).
Here is a complete, compilable program:
#include <iostream>
#include <type_traits>
using namespace std;
struct null_type { };
// Declare primary template
template<typename... Ts>
struct homogeneous_type;
// Base step
template<typename T>
struct homogeneous_type<T>
{
using type = T;
static const bool isHomogeneous = true;
};
// Induction step
template<typename T, typename... Ts>
struct homogeneous_type<T, Ts...>
{
// The underlying type of the tail of the parameter pack
using type_of_remaining_parameters = typename
homogeneous_type<Ts...>::type;
// True if each parameter in the pack has the same type
static const bool isHomogeneous =
is_same<T, type_of_remaining_parameters>::value;
// If isHomogeneous is "false", the underlying type is a fictitious type
using type = typename conditional<isHomogeneous, T, null_type>::type;
};
// Meta-function to determine if a parameter pack is homogeneous
template<typename... Ts>
struct is_homogeneous_pack
{
static const bool value = homogeneous_type<Ts...>::isHomogeneous;
};
template<typename T>
struct signature;
template<typename A, typename B>
struct signature<A (&)(B)>
{
using ret_type = A;
using arg_type = B;
};
template <typename F>
void foo(F&& f)
{
cout << f(42) << endl;
}
template <typename... F>
void foo(typename homogeneous_type<F...>::type f, F&&... fs)
{
static_assert(is_homogeneous_pack<F...>::value, "Not homogeneous!");
using fxn_type = typename homogeneous_type<F...>::type;
// This was template parameter A in your original code
using ret_type = typename signature<fxn_type>::ret_type;
// This was template parameter B in your original code
using arg_type = typename signature<fxn_type>::arg_type;
cout << f(42) << endl;
foo(fs...);
}
int fxn1(double i) { return i + 1; }
int fxn2(double i) { return i * 2; }
int fxn3(double i) { return i / 2; }
int fxn4(string s) { return 0; }
int main()
{
foo(fxn1, fxn2, fxn3); // OK
// foo(fxn1, fxn2, fxn4); // ERROR! not homogeneous signatures
return 0;
}
template <typename T>
struct helper;
template <typename F, typename B>
struct helper<F(B)> {
typedef F (*type)(B);
};
template<class F, class B>
void f()
{
}
template <class F, class B, typename... C>
void f(typename helper<F(B)>::type x, C... c)
{
std::cout << x(B(10)) << '\n';
f<F,B>(c...);
}
int identity(int i) { return i; }
int half(int i) { return i/2; }
int square(int i) { return i * i; }
int cube(int i) { return i * i * i; }
int main()
{
f<int,int>(identity,half,square,cube);
}
Here's a modified version that can deduce types:
template<class F, class B>
void f(F(*x)(B))
{
x(B());
}
template <class F, class B, typename... C>
void f(F(*x)(B), C... c)
{
f(x);
f<F,B>(c...);
}
int identity(int i) { return i; }
int half(int i) { return i/2; }
int square(int i) { return i * i; }
int cube(int i) { return i * i * i; }
int string_to_int(std::string) { return 42; }
int main()
{
f(identity,half,square,cube);
// f(identity,half,string_to_int);
}

templated iterator passing <N> to callback function

I am trying to run a compile-time iterator like:
meta::reverse_iterator<2, 9>::iterate(callback());
meta::reverse_iterator<4, 7>::iterate(callback());
std::cout << "-----------------" << std::endl;
meta::iterator<2, 9>::iterate(callback());
meta::iterator<4, 7>::iterate(callback());
struct callback {
template <int i>
void operator()() {
std::cout << "print !!" << i << std::endl;
}
};
and this is how I've written the meta-iterator:
namespace meta {
template <int Begin, int End, bool done = false>
struct reverse_iterator {
template <typename F>
static void iterate(F f) {
f.template operator()<End>();
reverse_iterator<Begin, End-1, Begin == End-1>::iterate(f);
}
};
template <int Begin, int End>
struct reverse_iterator<Begin, End, true> {
template <typename F>
static void iterate(F) {}
};
template <int Begin, int End, bool done = false>
struct iterator {
template <typename F>
static void iterate(F f) {
iterator<Begin, End - 1, Begin == End - 1>::iterate(f);
f.template operator()<End - 1>();
}
};
template <int Begin, int End>
struct iterator<Begin, End, true> {
template <typename F>
static void iterate(F) {}
};
}
Right now I iterator calls operator()<N> But I want it to be able to call any arbitrary function supplied by user with template parameter <N> (not as run-time argument) How can that be achieved ?
also boost::bind doesn't work with it as it calls the function object of bind instead of the real function. So there should be some way to carry default parameters to the supplied functions.
AFAIK you can't do it directly, but if you really want it you can use a traits class that call member function for you, and for different member functions write different traits:
struct function_operator_call_trait {
template< int N, class T >
void call( T& t ) {t.template operator()<N>();}
};
template< class Arg1, class Arg2 >
struct foo_call_trait {
foo_call_trait( Arg1&& arg1 ) : a1( std::move(arg1) ) {}
foo_call_trait( Arg1&& arg1, Arg2&& arg2 )
: a1( std::move(arg1) ), a2( std::move(arg2) ) {}
template< class T, int N >
void call( T& t ) {t.template foo<N>(a1, a2);}
Arg1 a1;
Arg2 a2;
};
template <int Begin, int End, class traits = function_operator_call_trait, bool done = false>
struct iterator{
iterator() {}
iterator( traits const& t ) : t_( t ) {}
iterator( traits&& t ) : t_( std::move(t) ) {}
template<typename F>
static void iterate(F f){
iterator<Begin, End-1, traits, Begin == End-1>::iterate(f);
t_.call<End-1>( f );
}
traits t_;
};
typedef iterator<2, 9> fc_iterator;
typedef foo_call_trait<int, float> foo_traits;
typedef iterator<2, 9, foo_traits> foo_iterator( foo_traits(1, 2) );