I have a class with a variadic template member function (foo) like below. The idea is to skip all doubles in the parameter and allocate an object with user provided arguments.
template <class T>
class Var {
public:
template <typename U, typename ...Args>
int foo(int index, Args... args)
{
T* p = new U(args...);
// save in an array at index 'index'
}
template <typename U, typename ...Args>
int foo (double index, Args... args)
{
// do something with index and skip it
return foo<U>(args...);
}
};
class A {
public:
A (int i, const char *p)
{
}
};
int main ()
{
Var<A> var;
var.foo<A>(1.0, 2, 3, "Okay");
}
Now this works, there are 2 problem.
Enforce how many doubles to skip.Eg: skip 2 doubles and then the next argument should be an int. If it is not then throw error.
While at it, use 'int' in place of 'double'. So we will skip 2 ints. The next index will be a 'index' to an array.
Basically I want to pass the no. of ints to skip as class template parameter.
template <class T, int SKIP>
class Var {
And use SKIP to determine how many ints to skip.
Is it possible to do something like that?
For your SKIP goal, you could do something like this:
template <typename U, typename ...Args>
int foo(Args ...args) {
return foo_helper<U, 0>(std::forward(args));
}
template <typename U, int I, typename ...Args>
int foo_helper(int index, Args ...args) {
return foo_helper<U, I+1>(std::forward(args));
}
template <typename U, typename ...Args>
int foo_helper<U, SKIP, Args...>(int index, Args ...args) {
blah = new U(std::forward(args));
return foobar;
}
Basically, have methods that count up to the target and strip off arguments until it's reached. Make a specialization for the target value.
Also, not that you'll probably want to forward the arguments to preserve references, etc.
I believe C++14 might make some of this easier, but I'm not familiar enough with newer template metaprogramming techniques to address that.
So this is what I conjured up taking hint from Novelocrat. Just pasting it hear for the records.
template <class T, int SKIP>
class FooHelper {
public:
template <typename U, typename ...Args>
static int foo_helper(int index, Args... args)
{
FooHelper<T, SKIP-1>::foo_helper<U>(args...);
return 0;
}
};
template <class T>
class FooHelper<T, 0> {
public:
template <typename U, typename ...Args>
static int foo_helper (Args... args)
{
auto p = new U(args...);
return 0;
}
};
template <class T, int SKIP>
class Var {
public:
template <typename U, typename ...Args>
int foo(Args ...args)
{
FooHelper<T, SKIP>::foo_helper<U>(args...);
return 0;
}
};
Related
I would like to check if there exist a member function with signature fit to a parameter pack. I began with the known SFINAE concept, while trying to extend it for considering also a parameters pack. But at this point I found that I don't know how to do it.
I try to do something like this:
// Note: T object may have several functions with the name foo, but with different signatures.
// a function foo also can be a template one with variadic parameters pack.
template<typename T, typename...Args>
class HAS_FUNCTION_FOO
{
template<typename U>
static bool test(decltype(&U::foo));
template<typename U>
static float test(...);
public:
static constexpr bool value = std::is_integral<decltype(test<T>(Args...))>::value;
//-------------------------------------------------------------^^^^^^^^^
// how to do it?
};
I would like to use it for declaring specific object at compile time - something like this:
class Bar
{
public:
template<typename T, typename...Args>
void doSomthing(T* p, Args&&...parameters)
{
// get correct object type:
// if T has a function called foo with parameters fits for pack, then declare A, o.w declare B.
using ObjType = typename std::conditional<HAS_FUNCTION_FOO<T, Args>::value, A, B>::type;
// compute
ObjType::doSomthing(p, std::forward<Args>(parameters)...);
}
private:
struct A
{
template<typename T, typename...Args>
static void doSomthing(T* p, Args&&...parameters)
{
p->foo(std::forward<Args>(parameters)...);
}
};
struct B
{
template<typename T, typename...Args>
static void doSomthing(T* p, Args&&...parameters)
{
// do something else
}
};
};
Something like this, perhaps:
template<typename T, typename...Args>
class HAS_FUNCTION_FOO
{
template <typename U>
static std::true_type test(
typename std::enable_if<sizeof(
decltype(std::declval<U>().foo(std::declval<Args>()...))*) != 0>::type*
);
template <typename U>
static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(nullptr))::value;
};
Demo
Consider I have the following:
void bar(int a, int b)
{
}
template<typename F, typename... Args>
void foo(F function, Args... args>
{
function(args...);
}
I would like to have some kind of way to only pass the necessary amount of arguments to the function, so that I would be able to do the following, which should result in a call to bar with 1, 2 as arguments discarding the 3. Without knowing how many arguments the passed in function type F needs.
foo(bar, 1, 2, 3);
foo([](int a, int b){}, 1, 2, 3);
When I try to use the below function traits:
namespace detail
{
template<typename F, std::size_t... Is, class Tup>
void call_discard_impl(F&& func, std::index_sequence<Is...>, Tup&& tup)
{
std::forward<F>(func)(std::get<Is>(tup)...);
}
}
template<typename F, typename... Args>
void call_discard(F&& func, Args&&... args)
{
detail::call_discard_impl(std::forward<F>(func),
std::make_index_sequence<function_traits<F>::num_args>{},
std::forward_as_tuple(args...));
}
I get:
error C2510: 'F': left of '::' must be a class/struct/union
error C2065: '()': undeclared identifier
error C2955: 'function_traits': use of class template requires template argument list
On:
template <typename F>
struct function_traits : public function_traits<decltype(&F::operator())>
{}
I did get the member function version working which did not require the function traits:
namespace detail
{
template<typename O, typename R, typename... FunArgs, std::size_t... Is, class Tup>
void call_discard_impl(O* obj, R(O::*mem_func)(FunArgs...), std::index_sequence<Is...>, Tup&& tup)
{
((*obj).*mem_func)(std::get<Is>(tup)...);
}
}
template<typename O, typename R, typename... FunArgs, typename... Args>
void call_discard(O* obj, R(O::*mem_func)(FunArgs...), Args&&... args)
{
detail::call_discard_impl(obj, mem_func,
std::make_index_sequence<sizeof...(FunArgs)>{},
std::forward_as_tuple(args...));
}
First, use the following code that lets you find the arity of a lambda or function reference:
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
using result_type = ReturnType;
using arg_tuple = std::tuple<Args...>;
static constexpr auto arity = sizeof...(Args);
};
template <typename R, typename ... Args>
struct function_traits<R(&)(Args...)>
{
using result_type = R;
using arg_tuple = std::tuple<Args...>;
static constexpr auto arity = sizeof...(Args);
};
Next, you forward the variadic arguments along using a tuple pack, and you only expand out to the arity of the function:
template<typename F, std::size_t... Is, class T>
void foo_impl(F && f, std::index_sequence<Is...>, T && tuple) {
std::forward<F>(f)(std::get<Is>(tuple)...);
}
template<typename F, typename... Args>
void foo(F && f, Args&&... args) {
foo_impl(std::forward<F>(f),
std::make_index_sequence<function_traits<F>::arity>{},
std::forward_as_tuple(args...) );
}
Live example: http://coliru.stacked-crooked.com/a/3ca5df7b55c427b8.
First, we need a function to retrieve the number or arguments the function requires. This is done using function_traits:
template <class F>
constexpr std::size_t nb_args() {
return utils::function_traits<F>::arity;
}
And with the help of std::index_sequence, we only dispatch the nb_args<F>() first arguments:
template<typename F, std::size_t... Is, class Tup>
void foo_impl(F && f, std::index_sequence<Is...>, Tup && tup) {
std::forward<F>(f)( std::get<Is>(tup)... );
}
template<typename F, typename... Args>
void foo(F && f, Args&&... args) {
foo_impl(std::forward<F>(f),
std::make_index_sequence<nb_args<F>()>{},
std::forward_as_tuple(args...) );
}
Demo
Trivial and hardly extensible solution would be to create a wrapper, that will be called with all arguments, but will use only first few of them.
template<typename F, typename... Args>
void foo(F function, Args... args)
{
// with proper forwarding if needed
auto lambda = [](auto fnc, auto first, auto second, auto...)
{
fnc(first, second);
};
lambda(function, args...);
}
Here is a solution that will work with anything std::invoke accepts, that invokes the overload with the fewest possible arguments.
template <typename F, typename Args, std::size_t... In>
decltype(auto) invoke_front_impl(F&& f, Args&& args, std::index_sequence<In...>)
{
if constexpr (std::is_invocable_v<F&&, std::tuple_element_t<In, Args>...>) {
return std::invoke(std::forward<F>(f), std::get<In>(std::move(args))...);
} else {
return invoke_front_impl(
std::forward<F>(f),
std::move(args),
std::make_index_sequence<sizeof...(In) + 1>());
}
}
template <typename F, typename... Args>
decltype(auto) invoke_front(F&& f, Args&&... args)
{
return invoke_front_impl(
std::forward<F>(f),
std::forward_as_tuple(std::forward<Args>(args)...),
std::make_index_sequence<0>());
}
Demo on Wandbox
So I was Playing around with c++11 Varidiacs, and I wanted to create a thing called CallClass, basically a class that warps a function, for later call,when all variables are set(truly I have No Idea If It can Be Useful):
#include <tuple>
template <typename OBJ,typename F,typename... VARGS>
class CallClass
{
public:
CallClass(OBJ& object,F callFunction)
:_object(&object),_func(callFunction)
{ }
CallClass(const CallClass& other)
:_func_args(other._func_args)
,_object(other._object)
,_func(other._func)
{ }
template <size_t INDEX>
auto get(){ return std::get<INDEX>(_func_args); }
template <size_t INDEX,typename T>
void set(const T& val){ std::get<INDEX>(_func_args) = val; }
template <size_t INDEX,typename T>
void set(T&& val){ std::get<INDEX>(_func_args) = val; }
auto Call()
{
//throws segmentation Fault Here
return InnerCall<0>(_func_args);
}
virtual ~CallClass() {}
protected:
private:
std::tuple<VARGS...> _func_args;
OBJ* _object;
F _func;
template <size_t INDEX,typename... ARGS>
auto InnerCall(std::tuple<VARGS...>& tup,ARGS... args)
{
auto arg = std::get<INDEX>(tup);
return InnerCall<INDEX + 1>(tup,args...,arg);
}
template <size_t INDEX,VARGS...>
auto InnerCall(std::tuple<VARGS...>& tup,VARGS... args)
{
return (_object->*_func)(args...);
}
};
Now when I try to compile(compiling using IDE:code::blocks, configured to use MINGW On windows ), it prints Compiler:Segmentation Fault, anybody any Ideas?
Usage:
class obj{
public:
obj(int a)
:_a(a)
{ }
virtual ~obj() {}
int add(int b,int c){
return _a + b + c;
}
private:
int _a;
};
int main(){
obj ob(6);
CallClass<obj,decltype(obj::add),int,int> callAdd(ob,obj::add);
callAdd.set<0,int>(5);
callAdd.set<1,int>(7);
cout << "result is " << callAdd.Call() << endl;
return 0;
}
After a Bit of a search i stumbled upon a similar issue, in a way.
apparently the way I'm unpacking the tuple is an issue, so i decided to use a different approach as shown in: enter link description here
had to add a few changes to suit my needs:
changes:
namespace detail
{
template <typename OBJ,typename F, typename Tuple, bool Done, int Total, int... N>
struct call_impl
{
static auto call(OBJ& obj,F f, Tuple && t)
{
return call_impl<OBJ,F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(obj,f, std::forward<Tuple>(t));
}
};
template <typename OBJ,typename F, typename Tuple, int Total, int... N>
struct call_impl<OBJ,F, Tuple, true, Total, N...>
{
static auto call(OBJ& obj,F f, Tuple && t)
{
return (obj.*f)(std::get<N>(std::forward<Tuple>(t))...);
}
};
}
// user invokes this
template <typename OBJ,typename F, typename Tuple>
auto call(OBJ& obj,F f, Tuple && t)
{
typedef typename std::decay<Tuple>::type ttype;
return detail::call_impl<OBJ,F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(obj,f, std::forward<Tuple>(t));
}
and changed Call():
auto Call()
{
std::tuple<VARGS...> func_args = _func_args;
return call(*_object,_func, std::move(func_args));
}
I will probably make a few more changes, like passing the tuple as a reference, and making the structs a part of my class.
I'm working on my own Lua engine with C++ 11, I want to write a function wrapper that register C++ function to Lua environment with variadic parameter. That's simple in C++ 0x, but boring cause I need to write similar codes to support function with 0~N parameters.
function push is used to push T to lua stack, where function upvalue_ get C++ function pointer with lua cclosure, and it assume the funtion is has two parameters T1 and T2, T1 is acquired from lua stack with index 1, and T2 is acquired from lua stack with index 2.
template <typename RVal, typename T1, typename T2>
struct functor<RVal,T1,T2>
{
static int invoke(lua_State *L)
{
push(L,upvalue_<RVal(*)(T1,T2)>(L)(read<T1>(L,1),read<T2>(L,2)));
return 1;
}
};
template<typename T>
T upvalue_(lua_State *L)
{
return user2type<T>::invoke(L, lua_upvalueindex(1));
}
and with C++ 11, I wrote such code snippets:
template< typename RVal, typename ... ARGS>
struct functor
{
static int invoke(lua_State* L)
{
typedef RVal (*FUNC_PTR)(ARGS...);
FUNC_PTR f = upvalue_<FUNC_PTR>(L);
push(L, f(read_stack<ARGS>(L)...));
return 1;
}
};
template<typename T>
T read_stack(lua_State* L)
{
T t = read<T>(L, -1);
lua_pop(L, 1);
return t;
}
the code shown above could work, but the parameter order is reversed because read_stack read parameter from the last index -1 always.
my question is how to read parameter from lua stack from 1 to N(N equals to sizeof...(ARGS) if ARGS not empty) with variadic template argument and pass them to real function pointer f to make real call?
Not specific to Lua, here is a general-purpose C++11 solution to reversing the order of given parameters to a function. In the below code, 'apply' is my example target function (here it just outputs a bit of text based on its variadic parameters). The 'main' functions shows how the helper function 'reverse_and_apply' takes a function (or Functor to be precise) and a set of arguments, and applies the given function to the reversed argument list using some template trickery. Note I apologise for the somewhat anal use of perfect forwarding here, which is technically correct but unfortunately obfuscates the code somewhat. Hopefully you get the main message.
#include <iostream>
template <typename ...Args>
void apply(const char* fmtString, const Args&... args)
{
char output[512];
snprintf(output, 512, fmtString, args...);
std::cout << output << std::endl;
}
template <typename F, typename ...Args>
struct ReverseAndApply;
template <typename F>
struct ReverseAndApply<F>
{
template <typename ... AlreadyReversed>
static void doIt(F func, AlreadyReversed&& ... args)
{
func(args...);
}
};
template <typename F, typename FirstArg, typename ...RestArgs>
struct ReverseAndApply<F, FirstArg, RestArgs...>
{
template <typename ... AlreadyReversed>
static void doIt(F func, FirstArg&& arg, RestArgs&& ... restArgs, AlreadyReversed&& ... revArgs)
{
ReverseAndApply<F, RestArgs...>::doIt(func, std::forward<RestArgs>(restArgs)..., std::forward<FirstArg>(arg), std::forward<AlreadyReversed>(revArgs)...);
}
};
template <typename F, typename... Args>
void reverse_and_apply(F func, Args&&... args)
{
ReverseAndApply<F, Args...>::doIt(func, std::forward<Args>(args)...);
}
int main()
{
reverse_and_apply(apply<double, const char*, int>, 1, (const char*)"abc", 2.0, "%f %s %d");
return 0;
}
Your code in C++11 not even work as the evaluation order of arguments is not defined.
It should be easy by using std::integer_sequence in C++14.
Sample code:
template< typename RVal, typename... ARGS>
struct functor
{
template <std::size_t... Is>
static int invoke_impl(lua_State *L, std::index_sequence<Is...>)
{
typedef RVal (*FUNC_PTR)(ARGS...);
FUNC_PTR f = upvalue_<FUNC_PTR>(L);
push(L, f(read<ARGS>(L, Is)...));
return 1;
}
static int invoke(lua_State* L)
{
return invoke_impl(L, std::index_sequence_for<ARGS...>{});
}
};
Using variadic template arguments together with a simple template argument I have experienced some strange behaviour of is_base_of when it was instantiated from a binded functor.
Here is the code:
template <class T, class Index>
class Base{};
template<typename T>
struct Checker {
typedef int result_type;
// Returns 1 if a given T type is descendant of Base<T,First>
template<typename First, typename ...Args>
result_type operator()(First&& first, Args&&... params)
{
return check(std::is_base_of<Base<T,First>, T>(),
std::forward<First>(first),
std::forward<Args>(params)...);
}
template<typename ...Args>
result_type check(const std::true_type&, Args&&... params)
{
return 1;
}
template<typename ...Args>
result_type check(const std::false_type&, Args&&... params)
{
return 0;
}
};
struct A {};
struct B : Base<B,int> {};
int main()
{
Checker<A> ch1;
std::cout<<ch1(3.14)<<std::endl;
Checker<B> ch2;
std::cout<<ch2(1 ,3.14)<<std::endl; // output is 1
std::cout<<std::bind(ch2, 1, 3.14)()<<std::endl; // output is 0 but it should be 1 !
return 0;
}
The program output is:
0
1
0
But I would expect:
0
1
1
Am I using the variadic templates in a wrong way? Is there any other (correct) way to get the first type of a variadic type list like Args? Why this is a problem only when it is used with the bind expression?
Note, if I am modifing the Base template to have only one template parameter, then the bind expression works:
template <class T>
class Base{};
template<typename T>
struct Checker {
typedef int result_type;
// Returns 1 if a given T type is descendant of Base<T>
template<typename ...Args>
result_type operator()(Args&&... params)
{
return check(std::is_base_of<Base<T>, T>(),
std::forward<Args>(params)...);
}
template<typename ...Args>
result_type check(const std::true_type&, Args&&... params)
{
return 1;
}
template<typename ...Args>
result_type check(const std::false_type&, Args&&... params)
{
return 0;
}
};
struct A {};
struct B : Base<B> {};
int main()
{
Checker<A> ch1;
std::cout<<ch1(3.14)<<std::endl;
Checker<B> ch2;
std::cout<<ch2(3.14)<<std::endl; // output is 1
std::cout<<std::bind(ch2, 3.14)()<<std::endl; // output is 1 this time!
return 0;
}
You're not getting the expected output because the data-type of First in your Checker function object when called after std::bind() is of type int&, not int.
Therefore std::is_base_of<Base<B,int&>, B> does not instantiate to a std::true_type for the call to Checker::check.
The problem is that std::bind is creating an object that internally stores the arguments for the function you are passing to it. Therefore there is a named l-value as a non-static data-member of the object returned by std::bind that is holding the value you passed as an argument to be bound to your function. When that non-static data-member is then passed to the r-value reference at the time you call the operator() of the functor, it's passed as an l-value reference, since it is no longer a temporary object. You would have a similar problem if you did something like:
int x = 1;
Checker<B> ch2;
std::cout<<ch2(x, 3.14)<<std::endl;
The named-value x is an l-value, and would be passed to the first argument in your operator() method as an l-value reference, not as temporary, since first is a r-value reference. Therefore your type would end up again as an int& and not an int, and you'd print a value of 0.
To fix this problem, you can do something like:
template<typename First, typename ...Args>
result_type operator()(First&& first, Args&&... params)
{
if (std::is_reference<First>::value)
{
return check(std::is_base_of<Base<T, typename std::remove_reference<First>::type>, T>(),
std::forward<First>(first),
std::forward<Args>(params)...);
}
else
{
return check(std::is_base_of<Base<T,First>, T>(),
std::forward<First>(first),
std::forward<Args>(params)...);
}
}
This will strip off the reference-type of the object and give you the results you want.
Unfortunately std::is_reference did not give me the expected result on a more complicated issue.
So finally I choosed providing the reference and const-reference overloads:
template<typename First, typename ...Args>
result_type operator()(First& first, Args&&... params)
{
return check(std::is_base_of<Base<T,First>, T>(),
first,
std::forward<Args>(params)...);
}
template<typename First, typename ...Args>
result_type operator()(const First& first, Args&&... params)
{
return check(std::is_base_of<Base<T,First>, T>(),
first,
std::forward<Args>(params)...);
}