I am trying to find way to design a class template so that an int value is passed, and several function signatures as well as argument lists are dependent on this value.
Particularly, considering MyClass:
template <int N>
class MyClass {
typedef SomeType<int, int, int, /* ... N times*/ > MyDepType;
myFunction(std::string arg0, std::string arg1, /* ...*/ std::string argN) { /* do stuff */};
public:
MyClass() {
someFunction(float arg0, float arg1, /* ...*/ float argN); // <
someOtherFunction(boost::bind(&MyClass::myFunction, this, _1, _2, /*...*/ _N));
};
};
I'd like to be able to express both the private typedef call, the signature of myFunction and the argument list passed to external functions someFunction and someOtherFunction, which I can't edit/rewrite.
Is there a way to achieve this, using the C++11 standard?
You could use a trick like in this post (Produce std::tuple of same type in compile time given its length by a template argument) to produce a tuple of N elements.
template <int N, typename T>
struct tuple_n_impl {
template <typename... Ts>
using type = typename tuple_n_impl<N - 1, T>::template type<T, Ts...>;
};
template <typename T>
struct tuple_n_impl<0, T> {
template <typename... Ts>
using type = std::tuple<Ts...>;
};
template <int N, typename T>
using tuple_n = typename tuple_n_impl<N, T>::template type<>;
template <int N>
class MyClass {
void int_function(tuple_n<N, int>&& ints);
void float_function(tuple_n<N, float>&& floats);
template <typename T>
void any_function(tuple_n<N, T>&& elements);
};
You might use std::index_sequence (C++14, but implementation in C++11 can be found on SO):
template <std::size_t, typename T>
using always_t = T;
template <std::size_t ... Is>
class MyClassImpl {
using MyDepType = SomeType<always_t<Is, int>...>;
void myFunction(always_t<Is, std::string>... args) { /* do stuff */}
public:
MyClass() {
void someFunction(always_t<Is, std::float>... args);
someOtherFunction([this](always_t<Is, const std::string&>... args) {
return myFunction(args...);
});
//
std::array<std::string, sizeof...(Is)> strings = {std::to_string(Is)...};
myFunction(strings[Is]...);
};
};
template <std::size_t N>
using MyClass = MyClassImpl<std::make_index_sequence<N>>;
Consider this function template:
template <class... T>
void foo (std::tuple<T, char, double> ... x);
This invocation works:
using K = std::tuple<int, char, double>;
foo ( K{1,'2',3.0}, K{4,'5',6.0}, K{7,'8',9.0} );
This one doesn't:
foo ( {1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0} );
(gcc and clang both complain about too many arguments for foo)
Why is the second call a problem? Can I rewrite the declaration of foo so that the second call is also accepted?
Thee template parameter T is only used to implement variadicity. The actual type is known and fixed, only the number of arguments varies. In real life the types are different from int, char, double, this is just an example.
I cannot use C++17 for this. A C++11-compatible solution is much preferred.
Generate an overloaded set of constructors:
#include <tuple>
#include <cstddef>
template <typename T, std::size_t M>
using indexed = T;
template <typename T, std::size_t M, std::size_t... Is>
struct initializer : initializer<T, M, sizeof...(Is) + 1, Is...>
{
using initializer<T, M, sizeof...(Is) + 1, Is...>::initializer;
initializer(indexed<T, Is>... ts)
{
// ts is a pack of std::tuple<int, char, double>
}
};
template <typename T, std::size_t M, std::size_t... Is>
struct initializer<T, M, M, Is...> {};
using foo = initializer<std::tuple<int, char, double>, 20>;
// tuples limit+1 ~~~^
int main()
{
foo({1,'2',3.0});
foo({1,'2',3.0}, {4,'5',6.0});
foo({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0});
}
DEMO
Generate an overloaded set of function call operators:
#include <tuple>
#include <cstddef>
template <typename T, std::size_t M>
using indexed = T;
template <typename T, std::size_t M, std::size_t... Is>
struct initializer : initializer<T, M, sizeof...(Is) + 1, Is...>
{
using initializer<T, M, sizeof...(Is) + 1, Is...>::operator();
int operator()(indexed<T, Is>... ts) const
{
// ts is a pack of std::tuple<int, char, double>
return 1;
}
};
template <typename T, std::size_t M, std::size_t... Is>
struct initializer<T, M, M, Is...>
{
int operator()() const { return 0; }
};
static constexpr initializer<std::tuple<int, char, double>, 20> foo = {};
// tuples limit+1 ~~~^
int main()
{
foo({1,'2',3.0});
foo({1,'2',3.0}, {4,'5',6.0});
foo({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0});
}
DEMO 2
Create (or generate with preprocessor macros) a set of overloads that forward arguments to a single implementation:
#include <array>
#include <tuple>
using K = std::tuple<int, char, double>;
void foo(const std::array<K*, 5>& a)
{
// a is an array of at most 5 non-null std::tuple<int, char, double>*
}
void foo(K p0) { foo({&p0}); }
void foo(K p0, K p1) { foo({&p0, &p1}); }
void foo(K p0, K p1, K p2) { foo({&p0, &p1, &p2}); }
void foo(K p0, K p1, K p2, K p3) { foo({&p0, &p1, &p2, &p3}); }
void foo(K p0, K p1, K p2, K p3, K p4) { foo({&p0, &p1, &p2, &p3, &p4}); }
int main()
{
foo({1,'2',3.0});
foo({1,'2',3.0}, {4,'5',6.0});
foo({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0});
}
DEMO 3
Pass as an array and deduce its size (requires additional pair of parens):
#include <tuple>
#include <cstddef>
template <std::size_t N>
void foo(const std::tuple<int, char, double> (&a)[N])
{
// a is an array of exactly N std::tuple<int, char, double>
}
int main()
{
foo({{1,'2',3.0}, {4,'5',6.0}});
// ^~~~~~ extra parens ~~~~~^
}
DEMO 4
Use an std::initializer_list as a constructor parameter (to skip extra parens):
#include <tuple>
#include <initializer_list>
struct foo
{
foo(std::initializer_list<std::tuple<int, char, double>> li)
{
// li is an initializer list of std::tuple<int, char, double>
}
};
int main()
{
foo{ {1,'2',3.0}, {4,'5',6.0} };
}
DEMO 5
{} is not an expression hence don't have type, argument deduction is concerned about types, special care is taken when the argument used to perform argument deduction is an initializer list the template function parameter must have specifics forms, otherwise the parameter is a non-deduced context. A more simplistic example is this:
template <class T> struct A { T r; };
template <class T>
void foo (A<T> x);
using K = A<int>;
foo({1}); // fail
foo(K{1}); // compile
This is covered by [temp.deduc.call]/1
If removing references and cv-qualifiers from P gives std::initializer_list<P'> or P'[N] for some P' and N and the argument is a non-empty initializer list ([dcl.init.list]), then deduction is performed instead for each element of the initializer list, taking P' as a function template parameter type and the initializer element as its argument, and in the P'[N] case, if N is a non-type template parameter, N is deduced from the length of the initializer list. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context
and [temp.deduct.type]/5
The non-deduced contexts are:
(5.6) A function parameter for which the associated argument is an initializer list ([dcl.init.list]) but the parameter does not have a type for which deduction from an initializer list is specified ([temp.deduct.call]).
When you:
explicitly provide template arguments, it works ... nothing to deduce
specify the argument as K{1}, it works ... the argument is not longer an initializer list, is an expression with type.
I cannot use C++17 for this. A C++11-compatible solution is much preferred.
With C++11 is a little more complicated (no std::index_sequence, no std::make_index_sequence) but, if you want maintain the variadic use of tuples... that is... if you substantially want something as
foo (std::tuple<int, char, double> ... ts)
and if you accept to call a static method of a template struct, you can define a template struct that recursively inherit itself and, recursively, define a
func ();
func (K t0);
func (K t0, K t1);
func (K t0, K t1, K t2);
where K is your
using K = std::tuple<int, char, double>;
The following is a full compiling C++11 example
#include <tuple>
#include <iostream>
using K = std::tuple<int, char, double>;
template <typename T, std::size_t>
struct getTypeStruct
{ using type = T; };
template <typename T, std::size_t N>
using getType = typename getTypeStruct<T, N>::type;
template <int ...>
struct iList;
template <std::size_t = 50u, std::size_t = 0u, typename = iList<>>
struct foo;
template <std::size_t Top, std::size_t N, int ... Is>
struct foo<Top, N, iList<Is...>> : public foo<Top, N+1u, iList<0, Is...>>
{
using foo<Top, N+1u, iList<0, Is...>>::func;
static void func (getType<K, Is> ... ts)
{ std::cout << sizeof...(ts) << std::endl; }
};
template <std::size_t Top, int ... Is>
struct foo<Top, Top, iList<Is...>>
{
// fake func, for recursion ground case
static void func ()
{ }
};
int main()
{
foo<>::func({1,'2',3.0}); // print 1
foo<>::func({1,'2',3.0}, {4,'5',6.0}); // print 2
foo<>::func({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0}); // print 3
}
If you can use C++14, you can use std::make_index_sequence and std::index_sequence and the code become a little better, IMHO
#include <tuple>
#include <iostream>
#include <type_traits>
using K = std::tuple<int, char, double>;
template <std::size_t ... Is>
constexpr auto getIndexSequence (std::index_sequence<Is...> is)
-> decltype(is);
template <std::size_t N>
using IndSeqFrom = decltype(getIndexSequence(std::make_index_sequence<N>{}));
template <typename T, std::size_t>
struct getTypeStruct
{ using type = T; };
template <typename T, std::size_t N>
using getType = typename getTypeStruct<T, N>::type;
template <std::size_t N = 50, typename = IndSeqFrom<N>>
struct foo;
template <std::size_t N, std::size_t ... Is>
struct foo<N, std::index_sequence<Is...>> : public foo<N-1u>
{
using foo<N-1u>::func;
static void func (getType<K, Is> ... ts)
{ std::cout << sizeof...(ts) << std::endl; }
};
template <>
struct foo<0, std::index_sequence<>>
{
static void func ()
{ std::cout << "0" << std::endl; }
};
int main()
{
foo<>::func({1,'2',3.0}); // print 1
foo<>::func({1,'2',3.0}, {4,'5',6.0}); // print 2
foo<>::func({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0}); // print 3
}
It's a pity you can't use C++17 because in you could use variadic unsing and avoid at all recursive inheritance
#include <tuple>
#include <iostream>
#include <type_traits>
using K = std::tuple<int, char, double>;
template <std::size_t ... Is>
constexpr auto getIndexSequence (std::index_sequence<Is...> is)
-> decltype(is);
template <std::size_t N>
using IndSeqFrom = decltype(getIndexSequence(std::make_index_sequence<N>{}));
template <typename T, std::size_t>
struct getTypeStruct
{ using type = T; };
template <typename T, std::size_t N>
using getType = typename getTypeStruct<T, N>::type;
template <std::size_t N, typename = IndSeqFrom<N>>
struct bar;
template <std::size_t N, std::size_t ... Is>
struct bar<N, std::index_sequence<Is...>>
{
static void func (getType<K, Is> ... ts)
{ std::cout << sizeof...(ts) << std::endl; }
};
template <std::size_t N = 50, typename = IndSeqFrom<N>>
struct foo;
template <std::size_t N, std::size_t ... Is>
struct foo<N, std::index_sequence<Is...>> : public bar<Is>...
{ using bar<Is>::func...; };
int main()
{
foo<>::func({1,'2',3.0}); // print 1
foo<>::func({1,'2',3.0}, {4,'5',6.0}); // print 2
foo<>::func({1,'2',3.0}, {4,'5',6.0}, {7,'8',9.0}); // print 3
}
This question already has answers here:
"unpacking" a tuple to call a matching function pointer
(9 answers)
Closed 5 years ago.
In C++14, you can do something like this:
struct Placeholder
{
template<typename T>
constexpr static T fct(T val) { return val; }
};
int main()
{
constexpr int i{};
auto fct = [](auto&& placeholder) -> decltype(placeholder.fct(i)) { return 5.5f; };
static_assert(fct(Placeholder{}) == 5, "");
}
For the sake of the example, consider that Placeholder::fct is actually manipulating the input type to something else (in the present case the function call is useless).
On the other hand, in C++11, you can simulate generic lambdas by declaring a templated functor. In fact, I could simply pass i to the constructor and store it as a member, like so:
template<typename T>
class Functor
{
T i;
public:
constexpr Functor(T i) : i{ i } {}
template<typename P>
constexpr auto operator()(P&& placeholder) const -> decltype(placeholder.fct(i))
{
return 5.5f;
}
};
int main()
{
constexpr int i{};
constexpr Functor<decltype(i)> fct(i);
static_assert(fct(Placeholder{}) == 5, "");
}
The problem comes when we want the Placeholder to take a variadic number of arguments, like so:
struct Placeholder
{
template<typename... T>
constexpr static auto fct(T... val) -> typename std::common_type<T...>::type
{
return { /* Do something with the values */ };
}
};
In fact, in C++14, we could simply pass the values directly to the lambda:
decltype(placeholder.fct(1, 2, 3))
However, in C++11, since we can't store a variadic number of members in a class, I don't see how I could achieve the exact same result. Any ideas?
From my understanding, a pure C++11 solution can be worked out from #RichardHodges 's idea. You need to recode std::apply by hand. To that end, you also need to recode std::integer_sequence, std::index_sequence and std::make_index_sequence. Let's start with that:
template <typename T, T... Is>
struct integral_sequence {};
template <std::size_t... Is>
using index_sequence = integral_sequence<std::size_t, Is...>;
template <typename Seq, typename T, T... el>
struct append_sequence;
template <typename T, T... el, T... Is>
struct append_sequence<integral_sequence<T, Is...>, T, el...> {
using type = integral_sequence<T, Is..., el...>;
};
namespace details {
template <std::size_t N>
struct make_index_sequence_impl {
private:
using seq = typename make_index_sequence_impl<N-1>::type;
public:
using type = typename append_sequence<seq, std::size_t, N>::type;
};
template <>
struct make_index_sequence_impl<0u> {
using type = index_sequence<0>;
};
template <std::size_t N>
struct make_index_sequence {
using type = typename make_index_sequence_impl<N-1>::type;
};
template <>
struct make_index_sequence<0u> {
using type = index_sequence<>;
};
} // namespace details
template <std::size_t N>
using make_index_sequence = typename details::make_index_sequence<N>::type;
Now, we can tackle the apply implementation. Its goal is to take a tuple as input and forward its content unpacked. For example, apply([](int x, int y) { /* impl */ }, std::make_tuple(0, 2)) is equivalent to [](int x, int y) { /* ... */ }(0, 2)
To do that we first need to dispatch a tuple content to a functor using an index_sequence:
namespace details {
template <typename F, typename Tuple, std::size_t... Is>
auto apply_impl(F&& ftor, Tuple&& tuple, index_sequence<Is...>) -> decltype(std::forward<F>(ftor)(std::get<Is>(tuple)...)) {
return std::forward<F>(ftor)(std::get<Is>(tuple)...);
}
} // namespace details
Then, the exposed apply comes in:
template <typename F, typename Tuple>
template <typename F, typename Tuple>
auto apply(F&& ftor, Tuple&& tuple) -> decltype(details::apply_impl(std::forward<F>(ftor), std::forward<Tuple>(tuple), make_index_sequence<std::tuple_size<typename std::remove_reference<Tuple>::type>::value>())){
return details::apply_impl(std::forward<F>(ftor), std::forward<Tuple>(tuple), make_index_sequence<std::tuple_size<typename std::remove_reference<Tuple>::type>::value>());
}
Now we can get the behavior you desired by storing a tuple inside your class and using apply to dispatch its content to your placeholder functor:
template <typename... Ts>
class Functor {
std::tuple<Ts...> is;
public:
constexpr Functor(Ts... ts) : is(std::make_tuple(ts...)) {}
template <typename P>
constexpr auto operator()(P&& placeholder) -> decltype(apply(std::forward<P>(placeholder), is)) {
return apply(std::forward<P>(placeholder), is);
}
};
Putting it all together with some examples leads to this Live Demo
Suppose I have the following function, that takes a function as a parameter.
template <typename F>
void test_func(F f)
{
// typedef typename function_traits<F>::return_type T;
typedef int T;
std::mt19937 rng(std::time(0));
std::uniform_int_distribution<T> uint_dist10(0, std::numeric_limits<T>::max());
f(uint_dist10(rng), uint_dist10(rng)); // Problem!
}
Usage would be:
int foo(int, int) { return 0; }
int bar(int, int, int, int) { return 0; }
int main()
{
test_func(foo);
// test_func(bar);
}
Just like foo and bar, I have several functions that return T, and take some amount of parameters of type T. I would like test_func to generate as many calls to my RNG as the function f takes parameters. In other words, we can assume T is always an integer type, and that each parameter will be the same, i.e. a function call to an RNG.
Using function_traits (such as the ones in Boost), I can fetch the return type of F, and that helps a little. Roughly, my question is
How can I generate a needed amount of function calls so that it matches the arity of the function F?
Before C++11, I would have looked at Boost.Preprocessor, or maybe relied on template specialization. Is there a nicer way of doing it now?
First define a meta function called arity to compute arity of the function (it is just a simple implementation; can be improved to compute arity of functors also. See my answer here.):
template<typename F>
struct arity;
template<typename R, typename ...Args>
struct arity<R (*)(Args...)>
{
static const std::size_t value = sizeof ... (Args);
};
then define another meta function called genseq to generate a compile time sequence of integral values:
template<int ... N>
struct seq
{
using type = seq<N...>;
template<int I>
struct push_back : seq<N..., I> {};
};
template<int N>
struct genseq : genseq<N-1>::type::template push_back<N-1> {};
template<>
struct genseq<0> : seq<> {};
template<int N>
using genseq_t = typename genseq<N>::type; //Just a friendly alias!
then a function invoker as:
template<typename F, typename ArgEvaluator, int ...N>
void invoke(seq<N...>, F f, ArgEvaluator arg_evaluator)
{
using arg_type = decltype(arg_evaluator());
constexpr std::size_t arity = sizeof ... (N);
arg_type args[] { (N, arg_evaluator()) ... }; //enforce order of evaluation
f( args[N] ... );
}
And then your code would become this:
template <typename F>
void test_func(F f)
{
// typedef typename function_traits<F>::return_type T;
typedef int T;
std::mt19937 rng(std::time(0));
std::uniform_int_distribution<T> uint_dist10(0, std::numeric_limits<T>::max());
//f(uint_dist10(rng), uint_dist10(rng)); // Problem!
auto arg_evaluator = [&]() mutable { return uint_dist10(rng); };
invoke(genseq_t<arity<F>::value>(), f, arg_evaluator);
}
Here is a sample demo.
Hope that helps.
No need for complicated meta calculations.
template <typename Ret, typename ... T>
void test_func (Ret f (T...))
{
std::mt19937 rng(std::time(0));
f((std::uniform_int_distribution<T>(0, std::numeric_limits<T>::max())(rng))...);
}
int moo(int, int, int){ return 0; }
int main ()
{
test_func(moo);
}
To support functors one needs a bit longer implementation, still not too complicated:
// separate arguments type from function/functor type
template <typename F, typename ... T>
void test_func_impl (F f)
{
std::mt19937 rng(std::time(0));
f((std::uniform_int_distribution<T>(0, std::numeric_limits<T>::max())(rng))...);
}
// overload for a straight function
template <typename Ret, typename ... T>
void test_func (Ret f (T...))
{
test_func_impl<decltype(f), T...>(f);
}
// forwarder for a functor with a normal operator()
template <typename F, typename Ret, typename... T>
void test_func_for_functor (F f, Ret (F::*)(T...))
{
test_func_impl<F, T...>(f);
}
// forwarder for a functor with a const operator()
template <typename F, typename Ret, typename... T>
void test_func_for_functor (F f, Ret (F::*)(T...)const)
{
test_func_impl<F, T...>(f);
}
// overload for anything that has operator()
template <typename F>
void test_func (F f)
{
test_func_for_functor(f, &F::operator());
}
For my current project, I've been writing a lot of C/C++ to Lua wrappers. A large number of these are simple setters and getters, so I managed to write some templates that make it easy to generate these, like so:
// Class Return Field
template <typename T, typename U, U T::*Member>
int luaU_get(lua_State* L)
{
T* obj = luaW_check<T>(L, 1);
luaU_push<U>(L, obj->*Member);
return 1;
}
static luaL_reg Foo_Table[] =
{
...
// Now I can just use this generic template to avoid
// writing simple getter functions
{ "getbar", luaU_get<Foo, Bar, &Foo::bar> },
...
};
I would like to do something similar for simple function wrappers for arbitrary functions too. For example, it would be nice to be able to do this:
template <typename T, typename U, U (T::*Func)(), typename... Args>
int luaU_func(lua_State* L)
{
// ...?
}
static luaL_reg Foo_Table[] =
{
...
{ "baz", luaU_func<Foo, int, &Foo::baz, int, float> },
...
};
The idea is that the template effectively turn out to be this when compiled:
int luaU_func(lua_State* L)
{
luaU_push<int>(L, luaW_check<Foo>(L, 1)->baz(luaU_check<int>(L, 2), luaU_check<float>(L, 3)));
return 1;
}
I've tried just using the ... expander, the problem for me is the integer index values to map to the proper arguments. I can't think of a way to get them working right. Is such a thing even possible?
(there is a little bit of magic going on here already; I wrote some templated wrappers for things like lua_push and lua_check. All of those existing wrappers can be found here)
The trick is to exploit template argument deduction by partially specializing a class template that contains the wrapper function:
// Lua API dummies ...
struct lua_State {};
template<class T> void luaU_push(lua_State*,T);
template<class T> T* luaW_check(lua_State*,int);
template<class T> T luaU_check(lua_State*,int);
// metaprogramming for creating indices ...
template<int...Ints>
struct int_pack {};
template<int Begin, int Count, int...Tail>
struct make_int_range_type {
typedef typename make_int_range_type<Begin,Count-1,Begin+Count-1,Tail...>::type type;
};
template<int Begin, int...Tail>
struct make_int_range_type<Begin,0,Tail...> {
typedef int_pack<Tail...> type;
};
template<int Begin, int Count>
inline typename make_int_range_type<Begin,Count>::type
make_int_range()
{ return typename make_int_range_type<Begin,Count>::type(); }
// the actual wrapper ...
template<class MemFunPtrType, MemFunPtrType PMF>
struct lua_mem_func_wrapper;
template<class Clazz, class ReturnType, class...Args, ReturnType(Clazz::*PMF)(Args...)>
struct lua_mem_func_wrapper<ReturnType(Clazz::*)(Args...),PMF> {
static int doit(lua_State* L) {
return doit_impl(L,make_int_range<2,sizeof...(Args)>());
}
private:
template<int...Indices>
static int doit_impl(lua_State* L, int_pack<Indices...>) {
luaU_push<ReturnType>(L,
(luaW_check<Clazz>(L, 1)->*PMF)(
luaU_check<Args>(L, Indices)...
)
);
return 1;
}
};
#define GET_MEM_FUN_WRAPPER(...) &lua_mem_func_wrapper<decltype(__VA_ARGS__),__VA_ARGS__>::doit
// testing ...
struct foo {
int baz(int, float);
};
void test() {
auto* ptr = GET_MEM_FUN_WRAPPER(&foo::baz);
}
This code compiles under G++ 4.6.1 using the options -c --std=c++0x. To see whether it really does what you want, please test it ...
Reusing the indices generation code from this answer and ignoring the function call to Func (don't know how exactly this is intended to be used), this is how it could look like:
template <typename T, typename U, U (T::*Func)(),
typename... Args, size_t... Idx>
int luaU_func_impl(lua_State* L, Collection<Idx...>)
{
luaU_push<int>(L, luaW_check<U>(L, 1), luaU_check<Args>(L, Idx+2)...);
return 1;
}
template <typename T, typename U, U (T::*Func)(), typename... Args>
int luaU_func(lua_State* L)
{
typename GenerateCollection<Args...>::type Indices;
return luaU_func_impl<T, U, Func, Args...>(L, Indices);
}