templated iterator passing <N> to callback function - c++

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) );

Related

unpack variadic template parameters

I have a template function:
template<typename R, typename... T>
void function(const std::string& id, R (*f)(T...)) {
switch (sizeof...(T)) {
case 0: f0compile<R>(reinterpret_cast<void (*)()>(f)); break;
case 1: f1compile<R, T>(reinterpret_cast<void (*)()>(f)); break;
case 2: f2compile<R, T1, T2>(reinterpret_cast<void (*)()>(f)); break;
}
...
}
How can I call these functions (f0compile, f1compile, f2compile) ? How can I write the "function" ?
template<typename R>
void f0compile(void (*f)()) {
new F0<R>(f):
...
}
template<typename R, typename T>
void f1compile(void (*f)()) {
new F1<R,T>(f);
...
}
template<typename R, typename T1, typename T2>
void f2compile(void (*f)()) {
new F2<R,T1,T2>(f);
...
}
Thank you for help with these variadic template.
I add the implementation of F0 F1 F2:
template <typename R> struct F0 : F {
F0(void (*_fn)()) : F(typeid(R))
, fn(reinterpret_cast<R(*)()>(_fn))
{}
const void* f() { res = fn(); return &res; }
R res; R (*fn)();
void d() { delete this; }
};
template <typename R, typename T> struct F1 : F {
F1(void (*_fn)(), F* _opd) : F(typeid(R))
, fn(reinterpret_cast<R(*)(T)>(_fn))
, opd(autocast<T>(_opd))
{}
const void* f() { res = fn(*(T*) opd->f()); return &res; }
F* opd;
R res; R (*fn)(T);
void d() { opd->d(); delete this; }
};
template <typename R, typename T1, typename T2> struct F2 : F {
F2(void (*_fn)(), F* _opd1, F* _opd2) : F(typeid(R))
, fn(reinterpret_cast<R(*)(T1,T2)>(_fn))
, opd1(autocast<T1>(_opd1))
, opd2(autocast<T2>(_opd2))
{}
const void* f() { res = fn(*(T1*) opd1->f(), *(T2*) opd2->f()); return &res; }
F* opd1; F* opd2;
R res; R (*fn)(T1,T2);
void d() { opd1->d(); opd2->d(); delete this; }
};
Thank you
struct F {
F(const std::type_info& _type) : type(_type) {}
virtual ~F() {}
const std::type_info& type;
virtual const void* f() = 0;
virtual void d() = 0;
};
Added class F . It rapresent each function / operand on the stack
template <typename T> struct Opd : F {
Opd(T _opd) : F(typeid(T)), res(_opd) { }
const void* f() { return &res; }
T res;
void d() { delete this; }
};
Added class Opd . It represent a specific operand on the stack.
The real program is this (simplified):
double foo(double op1, double op2) {
return op1 + op2;
}
#include <functional>
#include <stack>
#include <type_traits>
class Expression {
public:
struct F {
F(const std::type_info& _type) : type(_type) {}
virtual ~F() {}
const std::type_info& type;
virtual const void* f() = 0;
virtual void d() = 0;
};
public:
Expression() : m_cexpr(NULL) {}
~Expression() {
if (m_cexpr) m_cexpr->d();
}
// function
template<typename R, typename... T> void function(R (*f)(T...), void (*compile)(void (*)(), std::stack<F*>&)) {
m_f = std::make_pair(reinterpret_cast<void (*)()>(f), compile);
}
template<typename R, typename T1, typename T2> static void f2compile(void (*f)(), std::stack<F*>& s) {
auto opd2 = s.top();
s.pop();
auto opd1 = s.top();
s.pop();
s.push(new F2<R,T1,T2>(f, opd1, opd2));
}
void compile() {
if (m_cexpr) m_cexpr->d();
std::stack<F*> s;
s.push(new Opd<double>(1));
s.push(new Opd<double>(2));
m_f.second(m_f.first, s);
m_cexpr = s.top();
s.pop();
assert(s.empty());
}
void* execute() {
return const_cast<void*>(m_cexpr->f());
}
const std::type_info& type() {
return m_cexpr->type;
}
private:
F* m_cexpr;
std::pair<void (*)(), void (*)(void (*)(), std::stack<F*>&)> m_f;
template <typename T> struct Opd : F {
Opd(T _opd) : F(typeid(T)), res(_opd) {}
const void* f() { return &res; }
T res;
void d() { delete this; }
};
template <typename R, typename T1, typename T2> struct F2 : F {
F2(void (*_fn)(), F* _opd1, F* _opd2) : F(typeid(R))
, fn(reinterpret_cast<R(*)(T1,T2)>(_fn))
, opd1(_opd1)
, opd2(_opd2)
{}
const void* f() { res = fn(*(T1*) opd1->f(), *(T2*) opd2->f()); return &res; }
F* opd1; F* opd2;
R res; R (*fn)(T1,T2);
void d() { opd1->d(); opd2->d(); delete this; }
};
};
TEST_CASE("expression") {
Expression e;
e.function(foo, e.f2compile<double, double, double>);
e.compile();
e.execute();
REQUIRE(e.type() == typeid(double));
REQUIRE(*static_cast<double*>(e.execute()) == 3);
}
And my problem is how write better code c++11 using variadic template. How write a function "fNcompile" and a function "FN" with variadic template.
I don't think you need the variadic template. Instead:
template<typename R>
void fcompile(void (*f)()) {
new F0<R>(reinterpret_cast<void (*)()>(f));
...
}
template<typename R, typename T>
void fcompile(void (*f)(T)) {
new F1<R,T>(reinterpret_cast<void (*)()>(f));
...
}
template<typename R, typename T1, typename T2>
void fcompile(void (*f)(T1, T2)) {
new F1<R,T1,T2>(reinterpret_cast<void (*)()>(f));
...
}
Now you can call fcompile<some_type>(some_func) for any some_type and any nullary/unary/binary some_func which returns void.
To answer the specific question, below are variadic FN and fNcompile as close as possible to your existing code. First, though, since you said you're working in C++11, we'll need an equivalent of std::make_index_sequence from C++14. Here's a simple one. You can search for others that are smarter about being less likely to hit compiler template limitations...
namespace cxx_compat {
template <typename T, T... Values>
struct integer_sequence {
static constexpr std::size_t size() const
{ return sizeof...(Values); }
};
template <typename T, T Smallest, T... Values>
struct make_integer_sequence_helper {
static_assert(Smallest > 0,
"make_integer_sequence argument must not be negative");
using type = typename make_integer_sequence_helper<
T, Smallest-1, Smallest-1, Values...>::type;
};
template <typename T, T... Values>
struct make_integer_sequence_helper<T, 0, Values...> {
using type = integer_sequence<T, Values...>;
};
template <typename T, T N>
using make_integer_sequence =
typename make_integer_sequence_helper<T, N>::type;
template <std::size_t... Values>
using index_sequence = integer_sequence<std::size_t, Values...>;
template <std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
template <typename... T>
using index_sequence_for = make_index_sequence<sizeof...(T)>;
} // end namespace cxx_compat
And now, the actual FN and fNcompile:
template <typename R, typename ...T> struct FN : F {
private:
template <typename T>
using any_to_Fstar = F*;
public:
FN(void (*_fn)(), any_to_Fstar<T> ... _opd) : F(typeid(R))
, fn(reinterpret_cast<R(*)(T...)>(_fn))
, opd{_opd...}
{}
FN(R (*_fn)(T...)) : F(typeid(R)), fn(_fn), opd() {}
const void* f() {
f_helper(cxx_compat::index_sequence_for<T...>{});
return &res;
}
std::array<F*, sizeof...(T)> opd;
R res; R (*fn)(T...);
void d() {
for (F* o : opd)
o->d();
delete this;
}
private:
template <std::size_t... Inds>
void f_helper(cxx_compat::index_sequence<Inds...>)
{ res = fn(*(T*) opd[Inds]->f() ...); }
};
template<typename R, typename... T>
static void fNcompile(void (*f)(), std::stack<F*>& s) {
auto* f_obj = new FN<R, T...>(f);
for (std::size_t ind = sizeof...(T); ind > 0;) {
f_obj->opd[--ind] = s.top();
s.pop();
}
s.push(f_obj);
}
What's going on:
To actually call the function pointer, we need access to a number of function arguments at the same time, so to replace the named members opd1, opd2 with a number of F* pointers determined by template instantiation, we use a std::array<F*, sizeof...(T)>, since sizeof...(T) is the number of argument types provided to the template.
For compatibility with the F2 constructor you declared, any_to_Fstar<T> ... _opd declares a number of constructor parameters to match the number of T template arguments, all with the same type F*. (But now fNcompile uses the additional constructor taking just the function pointer instead, and sets the array members afterward.)
To get at these pointers and pass them all to fn in one expression, we need to expand some sort of variadic pack. Here's where index_sequence comes in:
index_sequence_for<T...> is a type alias for index_sequence with a sequence of numbers counting up from zero as template arguments. For example, if sizeof...(T) is 4, then index_sequence_for<T...> is index_sequence<0, 1, 2, 3>.
f just calls a private function f_helper, passing it an object of that index_sequence_for<T...> type.
The compiler can deduce the template argument list for f_helper from matching the index_sequence types: Inds... must be that same sequence of numbers counting up from zero.
In the f_helper body, the expression fn(*(T*) opd[Inds]->f() ...) is instantiated by expanding both the template parameter packs T and Inds to get one list of function arguments for calling fn.
However, use of void pointers and reinterpret_cast is dangerous and rarely actually necessary in C++. There's almost always a safer way using templates. So I'd redesign this to be something more like:
#include <type_traits>
#include <typeinfo>
#include <stdexcept>
#include <memory>
#include <stack>
namespace cxx_compat {
// Define integer_sequence and related templates as above.
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&& ... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
} // end namespace cxx_compat
class bad_expression_type : public std::logic_error
{
public:
bad_expression_type(const std::type_info& required,
const std::type_info& passed)
: logic_error("bad_argument_type"),
required_type(required),
passed_type(passed) {}
const std::type_info& required_type;
const std::type_info& passed_type;
};
class Expression
{
public:
class F
{
public:
F() noexcept = default;
F(const F&) = delete;
F& operator=(const F&) = delete;
virtual ~F() = default;
virtual const std::type_info& type() const noexcept = 0;
virtual void compile(std::stack<std::unique_ptr<F>>&) = 0;
template <typename R>
R call_R() const;
};
using F_ptr = std::unique_ptr<F>;
using F_stack = std::stack<F_ptr>;
template <typename R>
class Typed_F : public F
{
public:
const std::type_info& type() const noexcept override
{ return typeid(R); }
virtual R call() const = 0;
};
// Accepts any callable: function pointer, lambda, std::function,
// other class with operator().
template <typename R, typename... T, typename Func,
typename = typename std::enable_if<std::is_convertible<
decltype(std::declval<const Func&>()(std::declval<T>()...)),
R>::value>::type>
void function(Func func)
{
store_func<R, T...>(std::move(func));
}
// Overload for function pointer that does not need explicit
// template arguments:
template <typename R, typename... T>
void function(R (*fptr)(T...))
{
store_func<R, T...>(fptr);
}
template <typename T>
void constant(const T& value)
{
store_func<T>([value](){ return value; });
}
void compile(F_stack& stack)
{
m_cexpr->compile(stack);
}
private:
template <typename Func, typename R, typename... T>
class F_Impl : public Typed_F<R>
{
public:
F_Impl(Func func) : m_func(std::move(func)) {}
void compile(F_stack& stack) override {
take_args_helper(stack, cxx_compat::index_sequence_for<T...>{});
}
R call() const override {
return call_helper(cxx_compat::index_sequence_for<T...>{});
}
private:
template <typename Arg>
int take_one_arg(std::unique_ptr<Typed_F<Arg>>& arg, F_stack& stack)
{
auto* fptr = dynamic_cast<Typed_F<Arg>*>(stack.top().get());
if (!fptr)
throw bad_expression_type(
typeid(Arg), stack.top()->type());
arg.reset(fptr);
stack.top().release();
stack.pop();
return 0;
}
template <std::size_t... Inds>
void take_args_helper(F_stack& stack, cxx_compat::index_sequence<Inds...>)
{
using int_array = int[];
(void) int_array{ take_one_arg(std::get<Inds>(m_args), stack) ..., 0 };
}
template <std::size_t... Inds>
R call_helper(cxx_compat::index_sequence<Inds...>) const {
return m_func(std::get<Inds>(m_args)->call()...);
}
Func m_func;
std::tuple<std::unique_ptr<Typed_F<T>>...> m_args;
};
template <typename R, typename... T, typename Func>
void store_func(Func func)
{
m_cexpr = cxx_compat::make_unique<F_Impl<Func, R, T...>>(
std::move(func));
}
F_ptr m_cexpr;
};
template <typename R>
R Expression::F::call_R() const
{
auto* typed_this = dynamic_cast<const Typed_F<R>*>(this);
if (!typed_this)
throw bad_expression_type(typeid(R), type());
return typed_this->call();
}
TEST_CASE("expression") {
Expression a;
a.constant(1.0);
Expression b;
b.constant(2.0);
Expression c;
c.function(+[](double x, double y) { return x+y; });
Expression::F_stack stack;
a.compile(stack);
REQUIRE(stack.size() == 1);
b.compile(stack);
REQUIRE(stack.size() == 2);
c.compile(stack);
REQUIRE(stack.size() == 1);
REQUIRE(stack.top() != nullptr);
REQUIRE(stack.top()->type() == typeid(double));
REQUIRE(stack.top()->call_R<double>() == 3.0);
}
It would also be possible, but a bit tricky, to support reference and const variations of the argument and result types, for example, using a std::string(*)() function as an argument to an unsigned int(*)(const std::string&) function.

Termination issue on recursive template function in variadic template

I am trying to create a utility class that will call a specific function on all classes in a list. The purpose behind this is to automate an element of reflection within a hierarchy of classes.
I'm using Visual Studio 2015 to compile some C++ code and I'm getting a compile error when the recursive template function is unfolded because the compiler is having trouble distinguishing between the recursive function and the terminating function.
I've extracted out the core of the class to a simple test case:
#include <iostream>
template< typename ... BaseClasses >
class Meta
{
public:
virtual ~Meta() {}
template< typename T >
void call(const T& val)
{
callOnAllClasses<T, BaseClasses...>(val);
}
private:
template< typename T, typename HeadClass >
void callOnAllClasses(const T& val)
{
auto pObj = dynamic_cast<HeadClass*>(this);
if ( pObj )
pObj->HeadClass::doSomething(val);
}
template< typename T, typename HeadClass, typename ... TailClasses >
void callOnAllClasses(const T& val)
{
auto pObj = dynamic_cast<HeadClass*>(this);
if ( pObj )
pObj->HeadClass::doSomething(val);
callOnAllClasses<T, TailClasses...>(val);
}
};
class A
{
public:
void doSomething(int i)
{
std::cout << "A:" << i << std::endl;
}
};
class B
{
public:
void doSomething(int i)
{
std::cout << "B:" << i << std::endl;
}
};
class C : public B, public A, public Meta<C,B,A>
{
public:
void doSomething(int i)
{
std::cout << "C:" << i << std::endl;
}
};
int main()
{
C c;
c.call(5);
}
This results in the following error when compiled in Visual Studio 2015:
error C2668: 'Meta<C,B,A>::callOnAllClasses': ambiguous call to overloaded function
could be 'void Meta<C,B,A>::callOnAllClasses<T,A,>(const T &)'
or 'void Meta<C,B,A>::callOnAllClasses<T,A>(const T &)'
I've never used variadic templates before so I'm at a bit of a loss as to why this might be going wrong. Any help would be much appreciated!
You problem can be minimized as follows:
template< typename ... Bases >
struct Meta
{
template< typename T >
void call(const T& val)
{
callOnAllClasses<T, Bases...>(val);
}
template< typename T, typename HeadClass >
void callOnAllClasses(const T& val)
{
}
template< typename T, typename HeadClass, typename ... TailClasses >
void callOnAllClasses(const T& val)
{
callOnAllClasses<T, TailClasses...>(val);
}
};
struct C : Meta<int, int, int> { };
int main()
{
C{}.call(5);
}
When TailClasses is empty, both these signatures are ambiguous to the compiler:
template< typename T, typename HeadClass >
void callOnAllClasses(const T& val);
template< typename T, typename HeadClass, typename ... TailClasses >
void callOnAllClasses(const T& val);
Adding an extra template argument to the recursive case helps the compiler disambiguate between the variadic and non-variadic overloads when TailClasses is empty.
template< typename T, typename HeadClass, typename T1, typename ... TailClasses >
void callOnAllClasses(const T& val)
{
auto pObj = dynamic_cast<HeadClass*>(this);
if ( pObj )
pObj->HeadClass::doSomething(val);
callOnAllClasses<T, T1, TailClasses...>(val);
}
live example on godbolt

Specialize class for Base and all Derived

I have a Base-class and a derived class. I would like to design a Class C that reacts differently when a base or derived object is handed over like this:
template<typename T>
class Base {};
class Derived: public Base<int>{}
template<typename T>
class C
{
public:
static int f(T&& arg) {return 1;};
};
// Specialize C, not the function
template<typename T>
class C<T>
{
public:
static int f(T&& arg) {return 2;};
};
template<typename T>
int function(T&& arg) {
return C<T>::f(std::forward<T>(arg));
}
int main()
{
std::cout << function(1) << std::endl;
std::cout << function(Base<float>()) << std::endl;
std::cout << function(Derived()) << std::endl;
}
This is supposed to print:
1
2
2
Is there a way that I can do this with specializing the class C and not the function. In reality I just hand over the type C and everything happens out of my reach.
To clearify, the implementation of function may look like that but I can't really tell. All I know is the signature of f: int f(T&&); And that I have to have a class C that has a function of that signature.
Through Specialization of function():
Example code first:
template< class T >
struct Base
{};
struct Child : Base<int>
{ };
template<typename T>
class C1
{
public:
static int f(T&& arg) {return 1;}
};
template<typename T>
class C2
{
public:
static int f(T&& arg) {return 2;}
};
template<typename T>
typename std::enable_if< std::is_base_of<Base<int>, T>::value, int >::type function(T&& arg)
{
return C2<T>::f(std::forward<T>(arg));
}
template<typename T>
typename std::enable_if< !std::is_base_of<Base<int>, T >::value, int >::type function(T&& arg)
{
return C1<T>::f(std::forward<T>(arg));
}
int main()
{
std::cout << function(1) << std::endl;
std::cout << function(Base<int>()) << std::endl;
std::cout << function(Child()) << std::endl;
return 0;
}
Why:
So the split here is that I've written two versions of function(). The return type of function() looks a little hairy but the first version will be compiled if T has Base< int > as a base type. Otherwise the second version will be used.
std::enable_if<> is a neat tool which causes the template expansion to fail if its condition is not met. In this case we cause the template expansion to fail if T does not have Base< int > as a base class. In the case that the template expansion fails the compiler continues to look for another version of function() which will compile.
C1 and C2 are then two different objects with C2 being used if T has Base as a child, otherwise C1 is used.
Through Specialization of C:
template< class BaseArgument >
Base< BaseArgument > get_Base_type_of( Base< BaseArgument >&& );
template< class T >
struct has_Base
{
typedef char yes;
typedef long no;
template< typename T1 >
static yes Check( decltype( get_Base_type_of( declval<T1>() ) )* );
template< typename T1 >
static no Check( ... );
static const bool value = sizeof( decltype( Check<T>(0) ) ) == sizeof( yes ) ;
};
template< typename T, typename Placeholder = void >
class C
{
public:
static int f(T&& arg) {return 1;};
};
template<typename T>
class C< T, typename std::enable_if< has_Base<T>::value >::type >
{
public:
static int f(T&& arg) {return 2;};
};

How would I 'generate variadic parameters'?

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))...
};
}
};

Type sensitive tuple visitor

Suppose I have a std::tuple made up of types like
struct A {
static void tip();
};
struct B {
static void tip();
};
struct Z {
};
std::tuple<const A&,const B&,const Z&> tpl;
Yes, I need separate A, B. (The implementation of ::tip() differs for each type.) What I try to implement is a type-sensitive "visitor" that iterates through the tuple starting from the beginning to the end. Upon visiting a particular element of type T a function should be called depending on whether T has the ::tip() method or not. In the simple example of above only A and B have ::tip() implemented and Z not. So, the iterator should call twice the function for types with the ::tip() method and once the other function.
Here is what I came up with:
template< int N , bool end >
struct TupleIter
{
template< typename T , typename... Ts >
typename std::enable_if< std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}
template< typename T , typename... Ts >
typename std::enable_if< ! std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "no tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}
};
template< int N >
struct TupleIter<N,true>
{
template< typename T , typename... Ts >
static void Iter( const std::tuple<Ts...>& tpl ) {
std::cout << "end\n";
}
};
I use a dummy instance of the type of the element at the iterator position and decide via enable_if which function to call. Unfortunately this doesn't work/isn't a nice solution:
The compiler complains about recursive instantiation
The const T& dummy is not a clean solution
I was wondering if enable_if is the right strategy to do the decision and how can one recursively iterate through the std::tuple capturing the first type and keeping all the remaining arguments in vital state. Read through How to split a tuple? but it doesn't do any decision.
How can one implement such a thing in a correct and portable way in C++11?
Well, it was harder than I expected, but this works.
Some things you were doing wrong/that I modified:
You can't evaluate this: std::is_function< typename T::tip >::value, since T::tip is not a type. Even if this could be evaluated, what would happen when T::tip does not exist? Substitution would still fail.
Since you use const references as your tuple's inner types, you had to clean them before trying to find the tip member inside them. By cleaning I mean removing const and removing the reference.
That dummy type stuff was not a good idea, there was no need to use that parameter. You can achieve the same thing using std::tuple_element, which retrieves the i-th type from a tuple.
I modified TupleIter's template parameters to the following, which means:
"TupleIter that processes the index-th type, inside a tuple of size n".
template<size_t index, size_t n>
struct TupleIter;
The whole code is this:
#include <tuple>
#include <iostream>
#include <type_traits>
struct A {
static void tip();
};
struct B {
static void tip();
};
struct Z {
};
// Indicates whether the template parameter contains a static member named tip.
template<class T>
struct has_tip {
template<class U>
static char test(decltype(&U::tip));
template<class U>
static float test(...);
static const bool value = sizeof(test<typename std::decay<T>::type>(0)) == sizeof(char);
};
// Indicates whether the n-th type contains a tip static member
template<size_t n, typename... Ts>
struct nth_type_has_tip {
static const bool value = has_tip<typename std::tuple_element<n, std::tuple<Ts...>>::type>::value;
};
// Generic iteration
template<size_t index, size_t n>
struct TupleIter
{
template< typename... Ts >
typename std::enable_if< nth_type_has_tip<index, Ts...>::value , void >::type
static Iter(const std::tuple<Ts...>& tpl)
{
std::cout << "tip\n";
TupleIter<index + 1, n>::Iter(tpl );
}
template< typename... Ts >
typename std::enable_if< !nth_type_has_tip<index, Ts...>::value , void >::type
static Iter(const std::tuple<Ts...>& tpl) {
std::cout << "no tip\n";
TupleIter<index + 1, n>::Iter(tpl );
}
};
// Base class, we've reached the tuple end
template<size_t n>
struct TupleIter<n, n>
{
template<typename... Ts >
static void Iter( const std::tuple<Ts...>& tpl ) {
std::cout << "end\n";
}
};
// Helper function that forwards the first call to TupleIter<>::Iter
template<typename... Ts>
void iterate(const std::tuple<Ts...> &tup) {
TupleIter<0, sizeof...(Ts)>::Iter(tup);
}
int main() {
A a;
B b;
Z z;
std::tuple<const A&,const B&,const Z&> tup(a,b,z);
iterate(tup);
}
Here is another take on the question, very similar to mfontanini answer, but showcasing:
boost::fusion::for_each (instead of manually iterate over the tuple).
A variant for implementing has_type using an expression-based SFINAE approach, that I feel a little bit simpler to follow than the usual sizeof trick.
#include <boost/tuple/tuple.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/fusion/algorithm.hpp>
#include <iostream>
struct nat // not a type
{
private:
nat();
nat(const nat&);
nat& operator=(const nat&);
~nat();
};
template <typename T>
struct has_tip
{
static auto has_tip_imp(...) -> nat;
template <typename U>
static auto has_tip_imp(U&&) -> decltype(U::tip());
typedef decltype(has_tip_imp(std::declval<T>())) type;
static const bool value = !std::is_same<type, nat>::value;
};
struct CallTip
{
template<typename T>
typename std::enable_if<has_tip<T>::value>::type
operator()(T& t) const
{
std::cout << "tip\n";
T::tip();
}
template<typename T>
typename std::enable_if<!has_tip<T>::value>::type
operator()(T& t) const
{
std::cout << "no tip\n";
return;
}
};
struct A {
static void tip(){}
};
struct B {
static void tip(){}
};
struct Z {
};
int main()
{
A a;
B b;
Z z;
boost::tuple<const A&,const B&,const Z&> tpl(a, b, z);
boost::fusion::for_each(tpl, CallTip());
}
Note that if your compiler support variadic template you can use std::tuple instead of boost::tuple inside fusion::for_each by including #include<boost/fusion/adapted/std_tuple.hpp>
Edit :
As pointed by Xeo in the comment, it is possible to simplify a lot the expression-SFINAE approach by removing completely the trait has_tip and simply forward to a little call helper.
The final code is really neat and tight !
#include <boost/tuple/tuple.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/fusion/algorithm.hpp>
#include <iostream>
struct CallTip
{
template<typename T>
void operator()(const T& t) const
{
call(t);
}
template<class T>
static auto call(const T&) -> decltype(T::tip())
{
std::cout << "tip\n";
T::tip();
}
static void call(...)
{
std::cout << "no tip\n";
}
};
struct A {
static void tip(){}
};
struct B {
static void tip(){}
};
struct Z {
};
int main()
{
A a;
B b;
Z z;
boost::tuple<const A&,const B&,const Z&> tpl(a, b, z);
boost::fusion::for_each(tpl, CallTip());
}