Related
I have methods with the following signature:
void DoStuff(int i);
void DoStuff(int i, k);
void DoStuff(int i, int k, int l);
I have a method from where I would like to call the DoStuff methods as follows:
void CallDoStuff(const std::vector<int>& vElements) {
// What magic is supposed to happen here to make vElements an expandable pack?
DoStuff(vElemets...);
}
Is there any chance to achieve this?
Is using std::index_sequence the right way? If yes, could you please provide me a simple example how to apply this to my problem?
The problem is that, from a std::vector, you can't -- compile time -- extract the size() value.
So you can obtain what you want only if you pass, as a compile-time known value, to CallDoStuff() the number of elements that you want to use from the vector.
You can pass it as, by example, a template value.
Using an helper function, you can write something as follows
template <std::size_t ... Is>
void CallDoStuff (std::vector<int> const & vElements,
std::index_sequence<Is...> const &)
{ DoStuff(vElements[Is]...); }
template <std::size_t N>
void CallDoStuff (std::vector<int> const & vElements)
{ CallDoStuff(vElements, std::make_index_sequence<N>{}); }
The call could be something as
CallDoStuff<5u>(v);
If you can use a std::array, instead of std::vector, the answer is different: you can extract the size() from the type itself, so
template <std::size_t N, std::size_t ... Is>
void CallDoStuff (std::array<int, N> const & vElements,
std::index_sequence<Is...> const &)
{ DoStuff(vElements[Is]...); }
template <std::size_t N>
void CallDoStuff (std::array<int, N> const & vElements)
{ CallDoStuff(vElements, std::make_index_sequence<N>{}); }
that is callable without explicating N as follows
std::array<int, 5u> arr { 2, 3, 5, 7, 11 };
CallDoStuff(arr); // no more <5u>
End note: observe that std::make_index_sequence and std::index_sequence are available only starting from C++14. In C++11 you have to substitute them in some way.
It's possible, as long as you provide an upper bound to the number of arguments.
Using Xeo's implementation of std::index_sequence for C++11:
template <unsigned... Idx>
void trampoline(const std::vector<int>& vElements, seq<Idx...>) {
return DoStuff(vElements[Idx]...);
}
template <std::size_t Arity>
void trampoline(const std::vector<int>& vElements) {
return trampoline(vElements, typename gen_seq<Arity>::seq{});
}
template <unsigned... Idx>
void CallDoStuff(const std::vector<int>& vElements, seq<Idx...>) {
using trampoline_t = void (*)(const std::vector<int>&);
constexpr trampoline_t trampolines[]{
trampoline<Idx>...
};
trampolines[vElements.size()](vElements);
}
template <std::size_t Max>
void CallDoStuff(const std::vector<int>& vElements) {
assert(vElements.size() <= Max);
return CallDoStuff(vElements, typename gen_seq<Max + 1>::seq{});
}
See it live on Wandbox
This can't be done, a template method call is bound at compile time but a std::vector doesn't know how many items it contains until runtime so there's no way to mix the two concepts.
DoStuff(vElemets...);
Here the compiler should choose the correct implementation according to how many elements vElements has. You see the flaw in this kind of thinking since std::vector is just an object that could contain any amount of items at point of invocation.
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...>{});
}
};
I am writing a library that uses variadic-templated functions, like so:
template<typename ... T>
void func(T ... args) {
// ...
}
I need to ensure code is generated for this function (i.e. explicit instantiation) for certain types, like so:
template class func<int>;
template class func<int, int>;
template class func<int, int, int>;
// ...
where the max number of int arguments is a non-const maxArgs() (I am unable to change this as it is an external function). I have tried the following:
template<typename ... T>
void f(size_t max, T ... args) { // Generates "infinitely"
if (sizeof...(T) < max) {
func(args...);
f(max, args..., 0);
}
}
int main(int argc, char** argv) {
f(maxArgs(), 0);
// ...
return 0;
}
However the compiler doesn't have a proper base-case to the function generation recursion, so it fails to compile. I've also tried using non-type templates like so (using some code from here):
template<int ...> struct seq { };
template<int N, int ... Ns> struct gens : gens<N-1, N-1, Ns...> { };
template<int ... Ns> struct gens<0, Ns...> { typedef seq<Ns...> type; };
std::vector<int> params;
template<int ... Ns>
void f(seq<Ns...>) {
test(std::get<Ns>(params)...);
}
void instantiate(size_t max) {
for (int i = 1; i < max; ++i) {
for (int j = 0; j < i; ++j) {
params.push_back(0);
}
f(typename gens<i>::type()); // Fails to compile -- i is not const
params.clear();
}
}
int main(int argc, char** argv) {
instantiate(maxArgs());
}
but this requires a const value, so it fails to compile as well. Is there any way to do this properly having no knowledge of the return value of maxArgs()?
No, you cannot possibly generate at compile time templates which depend on a value only known at runtime. You will need to choose some maximum value which is a constant ahead of time (and sometimes not use all the instantiations), or figure out a way to make maxArgs() a compile-time constant. Or compile your code on the fly when it's used!
Since you have more information than we do about this code, perhaps you can think about whether making it be a variadic template is actually required. It seems likely that it isn't, given that the number of template arguments is determined at runtime. It might be better to write a solution which is fully runtime determined, without the variadic template stuff.
Since I know there is a maximum possible value to maxArgs() (namely 42), I came up with the following solution thanks to the suggestion of #JohnZwinck.
#include <vector>
typedef void (*void_fnptr)();
std::vector<void_fnptr> table;
// Function that needs to be code-generated for certain number of int types
template<typename ... T>
void func(T ... args) {
// ...
}
template<typename T>
void instantiate(T elem) {
table.push_back((void_fnptr)func<T>);
}
template<typename T, typename ... Ts>
void instantiate(T first, Ts ... rest) {
table.push_back((void_fnptr)func<T, Ts...>);
instantiate(rest...);
}
int main(int argc, char** argv) {
// 42 int arguments:
instantiate(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
// ...
return 0;
}
So i have something like that:
template<unsigned int W,unsigned int H>
class Class
{
int data[W][H];
Class(const (&_data)[W][H])
{
for (int x=0;x<W;x++)
for (int y=0;y<H;y++)
data[x][y] = _data[x][y];
}
template<class... args>
Class()
{
/// black magic
}
}
What could i replace the "black magic", so the second constructor will accept W*H ints?
Example:
Class<3,2> class1(1,2,3,4,5,6);
There are alternative answers which might be more practical and simpler to implement, but I'll show how you could actually do this with a compile-time for-loop for purposes of demonstrating black-magic.
Here is a compile-time for-loop.
/* Compile-time for-loop up to N. */
template <std::size_t N>
struct For {
/* Call f<I>(args...) N times. */
template <typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
Impl<0, N>()(std::forward<F>(f), std::forward<Args>(args)...);
}
private:
/* Forward declaration. */
template <std::size_t I, std::size_t End>
struct Impl;
/* Base case. Do nothing. */
template <std::size_t End>
struct Impl<End, End> {
template <typename F, typename... Args>
void operator()(F &&, Args &&...) const { /* Do nothing. */ }
}; // Impl<End, End>
/* Recursive case. Call f<I>(args...), then recurse into next step. */
template <std::size_t I, std::size_t End>
struct Impl {
template <typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
std::forward<F>(f).template operator()<I>(std::forward<Args>(args)...);
Impl<I + 1, End>()(std::forward<F>(f), std::forward<Args>(args)...);
}
}; // Impl<I, End>
}; // For<N>
Here is a simple use case of it.
struct Print {
template <std::size_t I>
void operator()(int x, int y) const {
std::cout << "Iteration " << I << ": " << x << ' ' << y << std::endl;
}
}; // Print
For<3>()(Print(), 1, 2);
Outputs
Iteration 0: 1 2
Iteration 1: 1 2
Iteration 2: 1 2
Now with this we can nest this compile-time for-loop just like how we could nest a run-time for-loop. Here is the Matrix class using this For<> template.
/* Defines an M by N Matrix, (Row by Col). */
template <std::size_t M, std::size_t N>
class Matrix {
public:
/* Our underlying M by N matrix. */
using Data = std::array<std::array<int, N>, M>;
/* Construct off of M * N arguments. */
template <typename... Args>
Matrix(Args &&... args) {
static_assert(sizeof...(Args) == M * N,
"The number of arguments provided must be M * N.");
ForEach(AssignImpl(),
data_,
std::forward_as_tuple(std::forward<Args>(args)...));
}
/* Print each element out to std::cout. */
void Write(std::ostream &strm) const {
ForEach(WriteImpl(), strm, data_);
}
private:
/* Our outer for loop. Call InnerFor() M times.
Resembles: 'for (std::size_t i = 0 ; i < M; ++i) {' */
template <typename F, typename... Args>
void ForEach(F &&f, Args &&... args) const {
For<M>()(InnerFor(), std::forward<F>(f), std::forward<Args>(args)...);
}
/* Our inner for loop. Call ForBody() N times.
Resembles: 'for (std::size_t j = 0; j < N; ++j) {' */
struct InnerFor {
template <std::size_t I, typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
For<N>()(ForBody<I>(),
std::forward<F>(f),
std::forward<Args>(args)...);
}
}; // InnerFor
/* The body of our for loop. Call f<I, J>(args...); */
template <std::size_t I>
struct ForBody {
template <std::size_t J, typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
std::forward<F>(f)
.template operator()<I, J>(std::forward<Args>(args)...);
}
}; // ForBody<I>
/* Given the M by N array and a tuple of length M * N, assign the array. */
struct AssignImpl {
template <std::size_t I, std::size_t J, typename Arg>
void operator()(Data &data, Arg &&arg) const {
data[I][J] = std::get<I * N + J>(std::forward<Arg>(arg));
}
}; // AssignImpl
/* Given an output stream and our data, print the data at (I, J). */
struct WriteImpl {
template <std::size_t I, std::size_t J>
void operator()(std::ostream &strm, const Data &data) const {
strm << data[I][J] << std::endl;
}
}; // WriteImpl
/* Our underlying M by N array. */
Data data_;
}; // Matrix
Here is a quick demonstration of construction and writing to std::cout.
int main() {
Matrix<3, 2> matrix{101, 102,
201, 202,
301, 302};
matrix.Write(std::cout);
}
First of all, there's some syntax errors in your example as missing semicolon after class declaration and the constructors being private.
Apart from that, if you want to store the numbers in row-major order, then you should declare your matrix/2d-array as int data[H][W] (height first, then width).
To store the values from a variadic pack you can simply expand them inside the ctor of a container, e.g. std::array, and make use of list-initialization.
template <typename... Args>
Class(Args&&... args) {
const std::array<int, H * W> temp{std::forward<Args>(args)...};
/* ... */
};
I've also used universal references and perfect forwarding to preserve the reference type of the pack.
To populate your 2d-array you simply have to iterate over all elements in temp and store them in the member array.
for (std::size_t h = 0; h != H; ++h)
for (std::size_t w = 0; w != W; ++w)
data[h][w] = temp[h * W + w];
See a full example here
This works:
#include <array>
#include <utility>
#include <iostream>
template<unsigned W,unsigned H>
struct Foo
{
std::array<std::array<int, H>, W> data;
template<typename... Args>
Foo(Args&&... args):
data{ std::forward<Args>(args)... }
{}
};
int main()
{
Foo<2,2> x(1,2,3,4);
for( auto&& a : x.data ) {
for( unsigned z : a ) {
std::cout << z << ",";
}
std::cout << "\n";
}
but exposes the order of storage in your inner array.
std::array is a syntactic sugar wrapped around raw C arrays.
you could use std::initializer_list as a constructor parameter, since your array only is of type int[][].
Class(std::initializer_list<int> il)
{
if(il.size() < W*H)
throw string("Insufficient elements");//if lesser no. of elements are given.
auto it = il.begin();// iterator to the first element of the list.
for(int i =0;i< W;++i)
{
for(int j =0; j < H;++j)
{
data[i][j] = *it++;// increment the iterator
}
}
}
call site will look like this:
Class<3,2> c{1,2,3,4,5,6};
or
Class<3,2> c = {1,2,3,4,5,6};
if more elements are given then extras are discarded. initializer_list can give type safety, and will give you a diagnostic if narrowing is found.