Compiletime for each with custom functions - c++

Abstract:
Imagine a problem of the following form: One has to invoke multiple specific member functions with the same parameters on a list of functors. That makes a good problem to solve with an interface (runtime_interface, in other words a requirement of functions that those functors have to implement). The Problem I would like to discuss is the case where the list of functors is known at compile time, but might be subject to change during the further development process. Because in this case if implemented like that one is paying the runtime overhead even though all the functions to be called are known at compile time.
General Question:
What are ways of solving Problems like the given one that come with no or just a small runtime overhead. without giving up the modularized structure.
I think what is really intresting about this is that its just
My approach:
template <class data_t, class... type_list_t>
struct compile_time_for_each_ref_impl;
template <class data_t, class first_t, class... type_list_t>
struct compile_time_for_each_ref_impl<data_t, first_t, type_list_t...> {
static void eval(const data_t& data, first_t& object, type_list_t... object_list)
{
std::apply(object, data);
compile_time_for_each_ref_impl<data_t, type_list_t...>::eval(data, object_list...);
}
};
template <class data_t>
struct compile_time_for_each_ref_impl<data_t> {
static void eval(const data_t& data) {}
};
template <class data_t, class... type_list_t>
void compile_time_for_each(const data_t& data, type_list_t&... objects)
{
compile_time_for_each_ref_impl<data_t, type_list_t...>::eval(data, objects...);
}
template <class data_t, class... type_list_t>
void compile_time_for_each(const data_t& data, std::tuple<type_list_t...>& objects)
{
std::apply(
[&data] (type_list_t... params) {
compile_time_for_each_ref_impl<data_t, type_list_t...>::eval(data, params...);
},
objects);
}
What I am able to:
int data = 42
auto functor_1 = [] (int data) {std::cout << data;};
auto functor_2 = [] (int data) {data++; std::cout << data;};
compile_time_for_each(std::make_tuple(data), functor1, functor2);
What the code i would like to write looks like::
struct functor1{
void method1(int);
int method2(double);
};
struct functor1{
void method1(int);
int method2(double);
};
template <class... functors_t>
struct main_mod{
std::tuple<functors_t...> functors;
void method1(int some_data){
compile_time_for_each<method1, functors_t...>(some_data,functors);
}
void method2(int some_data){
compile_time_for_each<method2, functors_t...>(some_data,functors);
}
};
The problem with my approach:
I dont see a way to pass the name of the function that is supposed to be called on the functor to the compile_time_for_each call. What i could do is to change the hardcoded function name (the example implementation takes the operator() because it makes the code simpler the code but one could hardcode any funtion name) so i would end up with one compile_time_for_each function for every function name that i would like to use.
One Solution(that I dont like to much):
A valid solution would be to make that whole thing a macro and set the actual name of the function in the macro.
At the end for me it is not really about the overhead but not beeing able to express theese things properly.
My actual implementation draft:
It incorporates #Aconcagua's idea of the resolver and the usage of fold expressions that #max66 suggested aswell. In this state I have not done any optimizations but I like the Interface and that was my main goal. Even though I think it should be doable without any overhead. If you are seeing this and have any ideas or suggestions hit me up.
https://godbolt.org/z/LfmSSb

Using a lambda I managed to get pretty close to what you intend, even though I failed to provide an exact match:
template<typename Executor, typename Data, typename ... Functors>
void for_each(Executor executor, Data const& data, Functors ... functors)
{
// C++17 fold expression:
(executor(functors, data), ...);
}
class C0
{
public:
void test0(int) const { std::cout << "00" << std::endl; }
void test1(int) const { std::cout << "01" << std::endl; }
};
class C1
{
public:
void test0(int) const { std::cout << "10" << std::endl; }
void test1(int) const { std::cout << "11" << std::endl; }
};
int main()
{
for_each([](auto const& c, int data) { c.test0(data); }, 7, C0(), C1());
for_each([](auto const& c, int data) { c.test1(data); }, 7, C0(), C1());
return 0;
}

Some observations.
1) if you want a compile time execution, you have to use constexpr.
So your compile_time_for_each() must be defined constexpr if you want that can be executed compile time
template <typename data_t, typename... type_list_t>
constexpr void compile_time_for_each (data_t const & data, type_list_t &... objects)
{ /* some potentially compile time code */ }
2) a constexpr function can be executed both compile time and run time; if you want impose that is executed compile-time... maybe there are other ways but the simplest mode come in my mind is return a value from the function
template <typename data_t, typename... type_list_t>
constexpr int compile_time_for_each (data_t const & data, type_list_t &... objects)
{
/* some potentially compile time code */
return 1;
}
and use the returned value to initialize a constexpr variable
constexpr auto x = compile_time_for_each(data, functor_1, functor_2);
3) for a compile time execution, you needs compile-time values, so define data as constexpr
constexpr int data = 42;
or its use prevents the compile time execution.
4) there is no needs of recursion: you tagged C++17 so you can use template folding; by example
template <typename D, typename ... Fs>
constexpr int compile_time_for_each (D const & data, Fs const & ... funcs)
{
(std::apply(funcs, data), ...);
return 0;
}
5) iostream input/output code isn't compatible with compile-time execution; so the following lambdas
auto functor_1 = [] (int data) {std::cout << data;};
auto functor_2 = [] (int data) {data++; std::cout << data;};
can't be executed compile-time.
The following is a C++17 example
#include <tuple>
template <typename D, typename ... Fs>
constexpr int ct_for_each (D const & data, Fs const & ... funcs)
{
(std::apply(funcs, data), ...);
return 0;
}
int main ()
{
constexpr int data = 42;
auto constexpr functor_1 = [] (int data) { /* some_code_1 */ };
auto constexpr functor_2 = [] (int data) { /* some_code_2 */ };
// compile time error if you define functor_1 as follows
// auto constexpr functor_1 = [] (int data) { std::cout << data << std::endl; };
constexpr auto x = ct_for_each(std::make_tuple(data), functor_1, functor_2);
(void)x; // to avoid "unused variable 'x'" warning
}

Related

Getting compile-time constant offsetof of base class in multiple-inheritance

Look at this example:
struct s77 {
char d[77];
};
struct s1 {
char d;
};
struct Foo: s77, s1 {
};
struct Off {
static const int v = std::size_t(static_cast<s1*>(static_cast<Foo*>(nullptr)+1)) - std::size_t(static_cast<Foo*>(nullptr)+1);
};
This code tries to put the offset of s1 in Foo into Off::v. This code compiles with GCC/clang (without any warnings), but fails to compile with VS2015/VS2017 (error C2131: expression did not evaluate to a constant)
Which compiler is correct?
Can I achieve this functionality in a standard conformant way? If it is not possible, is it possible to create a working solution which works with VS2015/VS2017? I'm willing to accept any working solution, even which has undefined behavior according to the standard (but happens to work with VS2015 and VS2017). Off::v must be a compile time constant.
My original problem is this: I have an own implementation of tuple, which is implemented with multiple inheritance (like clang's tuple). I'd like to create a compile-time constant "descriptor" for the tuple, which contains all of its members' offset in the tuple. This descriptor contains a function pointer for each tuple member too. If I'd create this descriptor by hand, it would look like this (for example):
struct Entry {
int offset;
void (*function)(void *member);
};
Entry descriptor[] = {
{ 0, &SomeType1::static_function },
{ 12, &SomeType2::static_function },
{ 20, &SomeType3::static_function }
};
The intention of this is that I could have a general function (which is not a template), which can use this descriptor to call a type-specific function on each tuple member:
void call(void *tuple, const Entry *entries, int n) {
for (int i=0; i<n; i++) {
entries[i].function(static_cast<char *>(tuple)+entries[i].offset);
}
}
(The reason of this solution instead of a templated call function is that call is actually a huge function in my real code, and entry[i].function calls cannot be factored out from it. I'd like to avoid massive code duplication.)
How about something like:
struct Entry {
void* (*data_member_getter)(void*);
void (*function)(void *member);
};
namespace details
{
template <std::size_t I, typename Tuple>
constexpr void* voidPGetter(void* tuple)
{
return &std::get<I>(*reinterpret_cast<Tuple*>(tuple));
}
template <typename Tuple, std::size_t I>
constexpr MakeEntry()
{
using type = std::tuple_element_t<I, Tuple>;
return { &voidPGetter<I, Tuple>, &type::static_function };
}
template <typename Tuple, std::size_t ... Is>
constexpr std::array<Entry, sizeof...(Is)>
ComputeEntryHelper(std::index_sequence<Is...>)
{
return {{MakeEntry<Is, Tuple>()...}};
}
}
template <typename Tuple>
constexpt auto ComputeEntry()
{
constexpr auto size = std::tuple_size<Tuple>::value;
return details::ComputeEntryHelper(std::make_index_sequence<size>());
}
And then
void call(void* tuple, const Entry* entries, int n) {
for (int i = 0; i != n; ++i) {
entries[i].function(entries[i].data_member_getter(tuple));
}
}
So instead of offset, having a function to get the data.

std::function with static allocation in c++

I am working in a memory constrained embedded environment where malloc/free new/delete are not advisable, and I'm trying to use the std::function pattern to register callbacks. I do not have access to any of the STL methods in my target code so I'm in the unfortunate situation of having to replicate some of the STL functionality myself. Function pointers are not an option for me due to the necessity for callers to have captures.
For instance, I wish to declare a class Mailbox where an onChange event can be registered
class Mailbox {
std::function<void(int,int)> onChange;
};
That way, callers can register a lambda onChange handler that could capture this or other variables that matter for handling the event.
Since this is part of an API, I want to give the users of Mailbox maximim flexibility to either provide a function pointer, a lambda or a functor.
I have managed to find a great implementation of a std::function that appears to be exceptionally low-overhead and has exactly what I need except that it involves dynamic memory.
If you look at the following code, dynamic memory is used in exactly one place, and it appears fully scoped to the object being templated, suggesting to me that its size ought to be known at compile-time.
Can anyone help me understand how to refactor this implementation so that it is fully static and removes the use of new/malloc? I'm having trouble understanding why the size of CallableT wouldn't be calculable at compile-time.
Code below (not for the faint of heart). Note, it uses make_unique / unique_ptr but those can easily be substituted with new and * and I have tested that use case successfully.
#include <iostream>
#include <memory>
#include <cassert>
using namespace std;
template <typename T>
class naive_function;
template <typename ReturnValue, typename... Args>
class naive_function<ReturnValue(Args...)> {
public:
template <typename T>
naive_function& operator=(T t) {
callable_ = std::make_unique<CallableT<T>>(t);
return *this;
}
ReturnValue operator()(Args... args) const {
assert(callable_);
return callable_->Invoke(args...);
}
private:
class ICallable {
public:
virtual ~ICallable() = default;
virtual ReturnValue Invoke(Args...) = 0;
};
template <typename T>
class CallableT : public ICallable {
public:
CallableT(const T& t)
: t_(t) {
}
~CallableT() override = default;
ReturnValue Invoke(Args... args) override {
return t_(args...);
}
private:
T t_;
};
std::unique_ptr<ICallable> callable_;
};
void func() {
cout << "func" << endl;
}
struct functor {
void operator()() {
cout << "functor" << endl;
}
};
int main() {
naive_function<void()> f;
f = func;
f();
f = functor();
f();
f = []() { cout << "lambda" << endl; };
f();
}
Edit: added clarification on STL
The name for what you're looking for is "in-place function". At least one very good implementation exists today:
sg14::inplace_function<R(A...), Size, Align>
There is also tj::inplace_any<Size, Align>, if you need/want the semantics of any.
Let me preface this answer by saying that storing a general callable faces an interesting choice in terms of memory management. Yes, we can deduce the size of any callable at compile time but we can not store any callable into the same object without memory management. That's because our own object needs to have size independently of the callables its supposed to store but those can be arbitrarily big.
To put this reasoning into one sentence: The layout of our class (and its interface) needs to be compiled without knowledge about all of the callers.
This leaves us with essentially 3 choices
We embrace memory management. We dynamically copy the callable and properly manage that memory through means of unique pointer (std or boost), or through custom calls to new and delete. This is what the original code you found does and is also done by std::function.
We only allow certain callables. We create some custom storage inside our object to hold some forms of callables. This storage has a pre-determined size and we reject any callable given that can not adhere to this requirement (e.g. by a static_assert). Note that this does not necessarily restrict the set of possible callers. Instead, any user of the interface could set up a proxy-class holding merely a pointer but forwarding the call operator. We could even offer such a proxy class ourselves as part of the library. But this does nothing more than shifting the point of allocation from inside the function implementation to outside. It's still worth a try, and #radosław-cybulski comes closest to this in his answer.
We don't do memory management. We could design our interface in a way that it deliberately refuses to take ownership of the callable given to it. This way, we don't need to to memory management and this part is completely up to our caller. This is what I will give code for below. It is not a drop-in replacement for std::function but the only way I see to have a generic, allocation-free, copiable type for the purpose you inteded it.
And here is the code for possibility 3, completely without allocation and fully self-contained (does not need any library import)
template<typename>
class FunctionReference;
namespace detail {
template<typename T>
static T& forward(T& t) { return t; }
template<typename T>
static T&& forward(T&& t) { return static_cast<T&&>(t); }
template<typename C, typename R, typename... Args>
constexpr auto get_call(R (C::* o)(Args...)) // We take the argument for sfinae
-> typename FunctionReference<R(Args...)>::ptr_t {
return [](void* t, Args... args) { return (static_cast<C*>(t)->operator())(forward<Args>(args)...); };
}
template<typename C, typename R, typename... Args>
constexpr auto get_call(R (C::* o)(Args...) const) // We take the argument for sfinae
-> typename FunctionReference<R(Args...)>::ptr_t {
return [](void* t, Args... args) { return (static_cast<const C*>(t)->operator())(forward<Args>(args)...); };
}
template<typename R, typename... Args>
constexpr auto expand_call(R (*)(Args...))
-> typename FunctionReference<R(Args...)>::ptr_t {
return [](void* t, Args... args) { return (static_cast<R (*)(Args...)>(t))(forward<Args>(args)...); };
}
}
template<typename R, typename... Args>
class FunctionReference<R(Args...)> {
public:
using signature_t = R(Args...);
using ptr_t = R(*)(void*, Args...);
private:
void* self;
ptr_t function;
public:
template<typename C>
FunctionReference(C* c) : // Pointer to embrace that we do not manage this object
self(c),
function(detail::get_call(&C::operator()))
{ }
using rawfn_ptr_t = R (*)(Args...);
FunctionReference(rawfn_ptr_t fnptr) :
self(fnptr),
function(detail::expand_call(fnptr))
{ }
R operator()(Args... args) {
return function(self, detail::forward<Args>(args)...);
}
};
For seeing how this then works in action, go to https://godbolt.org/g/6mKoca
Try this:
template <class A> class naive_function;
template <typename ReturnValue, typename... Args>
class naive_function<ReturnValue(Args...)> {
public:
naive_function() { }
template <typename T>
naive_function(T t) : set_(true) {
assert(sizeof(CallableT<T>) <= sizeof(callable_));
new (_get()) CallableT<T>(t);
}
template <typename T>
naive_function(T *ptr, ReturnValue(T::*t)(Args...)) : set_(true) {
assert(sizeof(CallableT<T>) <= sizeof(callable_));
new (_get()) CallableT<T>(ptr, t);
}
naive_function(const naive_function &c) : set_(c.set_) {
if (c.set_) c._get()->Copy(&callable_);
}
~naive_function() {
if (set_) _get()->~ICallable();
}
naive_function &operator = (const naive_function &c) {
if (this != &c) {
if (set_) _get()->~ICallable();
if (c.set_) {
set_ = true;
c._get()->Copy(&callable_);
}
else
set_ = false;
}
return *this;
}
ReturnValue operator()(Args... args) const {
return _get()->Invoke(args...);
}
ReturnValue operator()(Args... args) {
return _get()->Invoke(args...);
}
private:
class ICallable {
public:
virtual ~ICallable() = default;
virtual ReturnValue Invoke(Args...) = 0;
virtual void Copy(void *dst) const = 0;
};
ICallable *_get() {
return ((ICallable*)&callable_);
}
const ICallable *_get() const { return ((const ICallable*)&callable_); }
template <typename T>
class CallableT : public ICallable {
public:
CallableT(const T& t)
: t_(t) {
}
~CallableT() override = default;
ReturnValue Invoke(Args... args) override {
return t_(std::forward<ARGS>(args)...);
}
void Copy(void *dst) const override {
new (dst) CallableT(*this);
}
private:
T t_;
};
template <typename T>
class CallableT<ReturnValue(T::*)(Args...)> : public ICallable {
public:
CallableT(T *ptr, ReturnValue(T::*)(Args...))
: ptr_(ptr), t_(t) {
}
~CallableT() override = default;
ReturnValue Invoke(Args... args) override {
return (ptr_->*t_)(std::forward<ARGS>(args)...);
}
void Copy(void *dst) const override {
new (dst) CallableT(*this);
}
private:
T *ptr_;
ReturnValue(T::*t_)(Args...);
};
static constexpr size_t size() {
auto f = []()->void {};
return std::max(
sizeof(CallableT<void(*)()>),
std::max(
sizeof(CallableT<decltype(f)>),
sizeof(CallableT<void (CallableT<void(*)()>::*)()>)
)
);
};
typedef unsigned char callable_array[size()];
typename std::aligned_union<0, callable_array, CallableT<void(*)()>, CallableT<void (CallableT<void(*)()>::*)()>>::type callable_;
bool set_ = false;
};
Keep in mind, that sort of tricks tend to be slightly fragile.
In this case to avoid memory allocation i used unsigned char[] array of assumed max size - max of CallableT with pointer to function, pointer to member function and lambda object. Types of pointer to function and member function dont matter, as standard guarantees, that for all types those pointers will have the same size. Lambda should be pointer to object, but if for some reason isnt and it's size will change depending on lambda types, then you're out of luck.
First callable_ is initialized with placement new and correct CallableT type. Then, when you try to call, i use beginning of callable_ as pointer to ICallable. This all is standard safe.
Keep in mind, that you copy naive_function object, it's template argument T's copy operator is NOT called.
UPDATE: some improvements (at least try to force alignment) + addition of copying constructor / copy assignment.
My attempt to run the solution given Here, encountered with some issues. After fixing them, seems to work fine.
Will be happy for any review as I am not a c++ expert!
Issues and fixes:
error: lambda expression in an unevaluated operand.
removed the decltype. ( was not present in original code so I guess its safe(???)
using aligned_t = detail::aligned_union<0,
CallableT<void(*)()>,
//CallableT<decltype([]()->void {})>,
CallableT<void (CallableT<void(*)()>::*)()>
>;
Under C++11, errors in code block:
error: fields must have a constant size: 'variable length array in structure' extension will never be supported
error: 'aligned' attribute requires integer constant
error: constexpr variable 'alignment_value' must be initialized by a constant expression
(Note: this code is replacing std::aligned_union)
namespace detail {
template <size_t Len, class... Types>
struct aligned_union {
static constexpr size_t alignment_value = std::max({alignof(Types)...}); // ERROR HERE C++11
struct type {
alignas(alignment_value) char _s[std::max({Len, sizeof(Types)...})]; // ERROR HERE C++11
};
};
}
Used 'external' help from ETLCPP - which has support for embedded, file: largest.h.
Error block was replaced with :
#include"etl/largest.h"
template<typename ...Types>
using largest_t = typename etl::largest_type<Types...>::type;
namespace detail {
template <size_t Len, class... Types>
struct aligned_union {
static constexpr size_t alignment_value = etl::largest_alignment<Types...>::value; //std::max({alignof(Types)...});
struct type {
alignas(alignment_value) char _s[sizeof(largest_t<Types...>)]; //[std::max({Len, sizeof(Types)...})];
};
};
}
Looked redundant, removed:
//static constexpr size_t size() {
// auto f = []()->void {};
// return std::max(
// sizeof(CallableT<void(*)()>),
// std::max(
// sizeof(CallableT<decltype(f)>),
// sizeof(CallableT<void (CallableT<void(*)()>::*)()>)
// )
// );
//};
replaced std::forward with etl::forward file: utility.h
Had anew ,and delete errors : Undefined symbol operator delete
(void)*
So added ( I never allocate.. ):
// Define placement new if no new header is available
inline void* operator new(size_t, void* p) { return p; }
inline void* operator new[](size_t, void* p) { return p; }
inline void operator delete(void*, void*) {}
inline void operator delete[](void*, void*) {}
inline void operator delete[](void*) {}
Still getting a warning thought (???):
: warning: replacement function 'operator delete' cannot be declared 'inline' [-Winline-new-delete]
inline void operator delete(void* ) {}
Linker error:
Error: L6218E: Undefined symbol __cxa_pure_virtual ).
Probably because of virtual distractor : (ref)
virtual ~ICallable() = default;
Had to add this : ( any other solution ???)
extern "C" void __cxa_pure_virtual() { while (1); }

How to use generic template function to handle objects with different members?

I have looked around a while for a solution to this, however, I might not know the exact definition or language syntax of what I am trying to accomplish, so I decided to post.
I have certain objects/structs like so:
struct A
{
char myChar;
bool hasArray = false;
};
template <uint8_t ARRAY_LEN>
struct AA : public A
{
hasArray = true;
uint8_t myArray[ARRAY_LEN];
};
I want to create a generic function that can take in both of these object types and to perform common work as well as specific work for the derived struct AA. Something like the following:
template <typename T>
void func(T (&m))
{
if (T.hasArray)
{
// do some processing with m.myArray
std::cout << sizeof(m.myArray) << std::endl;
// ...
}
// common processing
std::cout << "myChar: " << m.myChar << std::endl;
};
I want to be able to call the function like so:
A a;
AA aa;
func(a); // compiler error, this would not work as no array member
func(aa); // this works
Granted this is just an example that illustrates my intent, but it sums up what I would like to do. The actual code is a lot more complex and involved many more objects. I know I can overload, but I want to know if there is a way to do it with one generic function? Also note that I understand why the compiler complains with the sample code I would like to know if there is a workaround or some other c++ functionality that I am missing. I would not like to do any type casting...
- Using c++11 and GCC 4.8.5
This is a C++14 feature of reasonably large complexity. C++17 introduced if constexpr to make this easier; but it is doable.
template<std::size_t I>
using index_t=std::integral_constant<std::size_t, I>;
template<std::size_t I>
constexpr index_t<I> index{};
constexpr inline index_t<0> dispatch_index() { return {}; }
template<class B0, class...Bs,
std::enable_if_t<B0::value, int> =0
>
constexpr index_t<0> dispatch_index( B0, Bs... ) { return {}; }
template<class B0, class...Bs,
std::enable_if_t<!B0::value, int> =0
>
constexpr auto dispatch_index( B0, Bs... ) {
return index< 1 + dispatch_index( decltype(Bs){}...) >;
}
template<class...Bs>
auto dispatch( Bs... ) {
using I = decltype(dispatch_index( decltype(Bs){}... ));
return [](auto&&...args)->decltype(auto){
return std::get<I::value>( std::make_tuple(decltype(args)(args)..., [](auto&&...){}) );
};
}
dispatch( some_test ) returns a lambda that takes auto&&.... It in turn returns the first argument if some_test is of a true-like-type, and the second argument (or [](auto&&...){} if no second argument) if some_test is of a false-like-type.
We then write code to detect your myArray.
namespace details {
template<template<class...>class Z, class=void, class...Ts>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = typename details::can_apply<Z, void, Ts...>::type;
template<class T>
using myArray_type = decltype( std::declval<T>().myArray );
template<class T>
using has_myArray = can_apply< myArray_type, T >;
and has_myArray<T> is true-like if T has a member .myArray.
We hook these together
dispatch( has_myArray<T>{} )(
[&](auto&& m) {
// do some processing with m.myArray
std::cout << sizeof(m.myArray) << std::endl;
// ...
}
)( m );
and now the lambda in the middle is run if and only if m.myArray is valid.
More complex tests that check for more than just existence can be written, but the above is usually sufficient.
In a non-C++11 compiler like MSVC 2015, replace
std::enable_if_t<B0::value, int> =0
and
std::enable_if_t<!B0::value, int> =0
with
class = std::enable_if_t<B0::value>
and
class = std::enable_if_t<!B0::value>, class=void
respectively. Yes, these are uglier. Go talk to MSVC compiler team.
If your compiler lacks C++14, you'll have to write your own void_t and either write your own enable_if_t or use the ugly longer version using enable_if.
In addition, the template variable index is illegal in C++11. Replace index<blah> with index_t<blah>{}.
The lack of auto&& lambdas makes the above very painful; you may have to convert the lambda to an out-of-line function object. However, auto lambdas where one of the first C++14 features people implemented, often before they finished C++11.
The above code is solid designed, but may contain typos.
Overloading works just fine in your case if you don't want to modify your instances:
#include<iostream>
#include<cstdint>
struct A
{
char myChar;
};
template <uint8_t ARRAY_LEN>
struct AA : public A
{
uint8_t myArray[ARRAY_LEN];
};
void func(const A &m)
{
std::cout << "myChar: " << m.myChar << std::endl;
};
template <uint8_t AL>
void func(const AA<AL> &m)
{
std::cout << sizeof(m.myArray) << std::endl;
func(static_cast<const A &>(m));
}
int main() {
func(A{});
func(AA<1>{});
}
If you still want to go with a template function and a bit of sfinae, I would probably use something like this instead:
#include<iostream>
#include<cstdint>
struct A
{
char myChar;
};
template <uint8_t ARRAY_LEN>
struct AA : public A
{
uint8_t myArray[ARRAY_LEN];
};
void func(A &m)
{
std::cout << "myChar: " << m.myChar << std::endl;
}
template <typename T>
auto func(T &m) -> decltype(m.myArray, void())
{
std::cout << sizeof(m.myArray) << std::endl;
A &a = m;
func(a);
}
int main() {
AA<1> aa{};
A a{};
func(a);
func(aa);
}
Note that in both cases you don't actually require the hasArray member data.
there is a way to do it with one generic function?
I don't think so, because if you insert a sizeof(m.myArray) in this function, you can't call it with a type without a myArray member. Even if it is in a part of code that, run time, isn't executed, because the compiler need to compile it.
But, if I understand correctly, your hasArray say if your struct has a myArray member or not. So I suppose you can transform it in a static constexpr member, as follows
struct A
{
static constexpr bool hasArray { false };
char myChar { 'z' };
};
template <uint8_t ARRAY_LEN>
struct AA : public A
{
static constexpr bool hasArray { true };
uint8_t myArray[ARRAY_LEN];
};
Now, in func(), you can call a second function, func2(), to choose the two cases: myArray or not myArray. You can use SFINAE for this but (IMHO) is better tag dispatching, in this case. So you can transform your hasArray in a different type
template <typename T>
void func2 (T const & m, std::true_type const &)
{ std::cout << sizeof(m.myArray) << ", "; }
template <typename T>
void func2 (T const &, std::false_type const &)
{ }
template <typename T>
void func(T (&m))
{
func2(m, std::integral_constant<bool, T::hasArray>{});
// common processing
std::cout << "myChar: " << m.myChar << std::endl;
}
Now you can call func() with both types
int main()
{
A a;
AA<12U> aa;
func(a); // print myChar: z
func(aa); // print 12, myChar: z
}
Remember to include type_traits and iostream.

how to avoid undefined execution order for the constructors when using std::make_tuple

How can I use std::make_tuple if the execution order of the constructors is important?
For example I guess the execution order of the constructor of class A and the constructor of class B is undefined for:
std::tuple<A, B> t(std::make_tuple(A(std::cin), B(std::cin)));
I came to that conclusion after reading a comment to the question
Translating a std::tuple into a template parameter pack
that says that this
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
implementation has an undefined execution order of the constructors.
Update, providing some context:
To give some more background to what I am trying to do, here is a sketch:
I want to read in some serialized objects from stdin with the help of CodeSynthesis XSD binary parsing/serializing. Here is an example of how such parsing and serialization is done: example/cxx/tree/binary/xdr/driver.cxx
xml_schema::istream<XDR> ixdr (xdr);
std::auto_ptr<catalog> copy (new catalog (ixdr));
I want to be able to specify a list of the classes that the serialized objects have (e.g. catalog, catalog, someOtherSerializableClass for 3 serialized objects) and store that information as a typedef
template <typename... Args>
struct variadic_typedef {};
typedef variadic_typedef<catalog, catalog, someOtherSerializableClass> myTypes;
as suggested in Is it possible to “store” a template parameter pack without expanding it?
and find a way to get a std::tuple to work with after the parsing has finished. A sketch:
auto serializedObjects(binaryParse<myTypes>(std::cin));
where serializedObjects would have the type
std::tuple<catalog, catalog, someOtherSerializableClass>
The trivial solution is not to use std::make_tuple(...) in the first place but to construct a std::tuple<...> directly: The order in which constructors for the members are called is well defined:
template <typename>
std::istream& dummy(std::istream& in) {
return in;
}
template <typename... T>
std::tuple<T...> parse(std::istream& in) {
return std::tuple<T...>(dummy<T>(in)...);
}
The function template dummy<T>() is only used to have something to expand on. The order is imposed by construction order of the elements in the std::tuple<T...>:
template <typename... T>
template <typename... U>
std::tuple<T...>::tuple(U...&& arg)
: members_(std::forward<U>(arg)...) { // NOTE: pseudo code - the real code is
} // somewhat more complex
Following the discussion below and Xeo's comment it seems that a better alternative is to use
template <typename... T>
std::tuple<T...> parse(std::istream& in) {
return std::tuple<T...>{ T(in)... };
}
The use of brace initialization works because the order of evaluation of the arguments in a brace initializer list is the order in which they appear. The semantics of T{...} are described in 12.6.1 [class.explicit.init] paragraph 2 stating that it follows the rules of list initialization semantics (note: this has nothing to do with std::initializer_list which only works with homogenous types). The ordering constraint is in 8.5.4 [dcl.init.list] paragraph 4.
As the comment says, you could just use initializer-list:
return std::tuple<args...>{args(stream)...};
which will work for std::tuple and suchlikes (which supports initializer-list).
But I got another solution which is more generic, and can be useful where initializer-list cannot be used. So lets solve this without using initializer-list:
template<typename... args>
std::tuple<args...> parse(std::istream &stream) {
return std::make_tuple(args(stream)...);
}
Before I explain my solution, I would like to discuss the problem first. In fact, thinking about the problem step by step would also help us to come up with a solution eventually. So, to simply the discussion (and thinking-process), lets assume that args expands to 3 distinct types viz. X, Y, Z, i.e args = {X, Y, Z} and then we can think along these lines, reaching towards the solution step-by-step:
First and foremost, the constructors of X, Y, and Z can be executed in any order, because the order in which function arguments are evaluated is unspecified by the C++ Standard.
But we want X to construct first, then Y, and Z. Or at least we want to simulate that behavior, which means X must be constructed with data that is in the beginning of the input stream (say that data is xData) and Y must be constructed with data that comes immediately after xData, and so on.
As we know, X is not guaranteed to be constructed first, so we need to pretend. Basically, we will read the data from the stream as if it is in the beginning of the stream, even if Z is constructed first, that seems impossible. It is impossible as long as we read from the input stream, but we read data from some indexable data structure such as std::vector, then it is possible.
So my solution does this: it will populate a std::vector first, and then all arguments will read data from this vector.
My solution assumes that each line in the stream contains all the data needed to construct an object of any type.
Code:
//PARSE FUNCTION
template<typename... args>
std::tuple<args...> parse(std::istream &stream)
{
const int N = sizeof...(args);
return tuple_maker<args...>().make(stream, typename genseq<N>::type() );
}
And tuple_maker is defined as:
//FRAMEWORK - HELPER ETC
template<int ...>
struct seq {};
template<int M, int ...N>
struct genseq : genseq<M-1,M-1, N...> {};
template<int ...N>
struct genseq<0,N...>
{
typedef seq<N...> type;
};
template<typename...args>
struct tuple_maker
{
template<int ...N>
std::tuple<args...> make(std::istream & stream, const seq<N...> &)
{
return std::make_tuple(args(read_arg<N>(stream))...);
}
std::vector<std::string> m_params;
std::vector<std::unique_ptr<std::stringstream>> m_streams;
template<int Index>
std::stringstream & read_arg(std::istream & stream)
{
if ( m_params.empty() )
{
std::string line;
while ( std::getline(stream, line) ) //read all at once!
{
m_params.push_back(line);
}
}
auto pstream = new std::stringstream(m_params.at(Index));
m_streams.push_back(std::unique_ptr<std::stringstream>(pstream));
return *pstream;
}
};
TEST CODE
///TEST CODE
template<int N>
struct A
{
std::string data;
A(std::istream & stream)
{
stream >> data;
}
friend std::ostream& operator << (std::ostream & out, A<N> const & a)
{
return out << "A" << N << "::data = " << a.data ;
}
};
//three distinct classes!
typedef A<1> A1;
typedef A<2> A2;
typedef A<3> A3;
int main()
{
std::stringstream ss("A1\nA2\nA3\n");
auto tuple = parse<A1,A2,A3>(ss);
std::cout << std::get<0>(tuple) << std::endl;
std::cout << std::get<1>(tuple) << std::endl;
std::cout << std::get<2>(tuple) << std::endl;
}
Output:
A1::data = A1
A2::data = A2
A3::data = A3
which is expected. See demo at ideone yourself. :-)
Note that this solution avoids the order-of-reading-from-the-stream problem by reading all the lines in the first call to read_arg itself, and all the later calls just read from the std::vector, using the index.
Now you can put some printf in the constructor of the classes, just to see that the order of construction is not same as the order of template arguments to the parse function template, which is interesting. Also, the technique used here can be useful for places where list-initialization cannot be used.
There's nothing special about make_tuple here. Any function call in C++ allows its arguments to be called in an unspecified order (allowing the compiler freedom to optimize).
I really don't suggest having constructors that have side-effects such that the order is important (this will be a maintenance nightmare), but if you absolutely need this, you can always construct the objects explicitly to set the order you want:
A a(std::cin);
std::tuple<A, B> t(std::make_tuple(a, B(std::cin)));
This answer comes from a comment I made to the template pack question
Since make_tuple deduces the tuple type from the constructed components and function arguments have undefined evaluation ordder, the construction has to happen inside the machinery, which is what I proposed in the comment. In that case, there's no need to use make_tuple; you could construct the tuple directly from the tuple type. But that doesn't order construction either; what I do here is construct each component of the tuple, and then build a tuple of references to the components. The tuple of references can be easily converted to a tuple of the desired type, provided the components are easy to move or copy.
Here's the solution (from the lws link in the comment) slightly modified, and explained a bit. This version only handles tuples whose types are all different, but it's easier to understand; there's another version below which does it correctly. As with the original, the tuple components are all given the same constructor argument, but changing that simply requires adding a ... to the lines indicated with // Note: ...
#include <tuple>
#include <type_traits>
template<typename...T> struct ConstructTuple {
// For convenience, the resulting tuple type
using type = std::tuple<T...>;
// And the tuple of references type
using ref_type = std::tuple<T&...>;
// Wrap each component in a struct which will be used to construct the component
// and hold its value.
template<typename U> struct Wrapper {
U value;
template<typename Arg>
Wrapper(Arg&& arg)
: value(std::forward<Arg>(arg)) {
}
};
// The implementation class derives from all of the Wrappers.
// C++ guarantees that base classes are constructed in order, and
// Wrappers are listed in the specified order because parameter packs don't
// reorder.
struct Impl : Wrapper<T>... {
template<typename Arg> Impl(Arg&& arg) // Note ...Arg, ...arg
: Wrapper<T>(std::forward<Arg>(arg))... {}
};
template<typename Arg> ConstructTuple(Arg&& arg) // Note ...Arg, ...arg
: impl(std::forward<Arg>(arg)), // Note ...
value((static_cast<Wrapper<T>&>(impl)).value...) {
}
operator type() const { return value; }
ref_type operator()() const { return value; }
Impl impl;
ref_type value;
};
// Finally, a convenience alias in case we want to give `ConstructTuple`
// a tuple type instead of a list of types:
template<typename Tuple> struct ConstructFromTupleHelper;
template<typename...T> struct ConstructFromTupleHelper<std::tuple<T...>> {
using type = ConstructTuple<T...>;
};
template<typename Tuple>
using ConstructFromTuple = typename ConstructFromTupleHelper<Tuple>::type;
Let's take it for a spin
#include <iostream>
// Three classes with constructors
struct Hello { char n; Hello(decltype(n) n) : n(n) { std::cout << "Hello, "; }; };
struct World { double n; World(decltype(n) n) : n(n) { std::cout << "world"; }; };
struct Bang { int n; Bang(decltype(n) n) : n(n) { std::cout << "!\n"; }; };
std::ostream& operator<<(std::ostream& out, const Hello& g) { return out << g.n; }
std::ostream& operator<<(std::ostream& out, const World& g) { return out << g.n; }
std::ostream& operator<<(std::ostream& out, const Bang& g) { return out << g.n; }
using std::get;
using Greeting = std::tuple<Hello, World, Bang>;
std::ostream& operator<<(std::ostream& out, const Greeting &n) {
return out << get<0>(n) << ' ' << get<1>(n) << ' ' << get<2>(n);
}
int main() {
// Constructors run in order
Greeting greet = ConstructFromTuple<Greeting>(33.14159);
// Now show the result
std::cout << greet << std::endl;
return 0;
}
See it in action on liveworkspace. Verify that it constructs in the same order in both clang and gcc (libc++'s tuple implementation holds tuple components in the reverse order to stdlibc++, so it's a reasonable test, I guess.)
To make this work with tuples which might have more than one of the same component, it's necessary to modify Wrapper to be a unique struct for each component. The easiest way to do this is to add a second template parameter, which is a sequential index (both libc++ and libstdc++ do this in their tuple implementations; it's a standard technique). It would be handy to have the "indices" implementation kicking around to do this, but for exposition purposes, I've just done a quick-and-dirty recursion:
#include <tuple>
#include <type_traits>
template<typename T, int I> struct Item {
using type = T;
static const int value = I;
};
template<typename...TI> struct ConstructTupleI;
template<typename...T, int...I> struct ConstructTupleI<Item<T, I>...> {
using type = std::tuple<T...>;
using ref_type = std::tuple<T&...>;
// I is just to distinguish different wrappers from each other
template<typename U, int J> struct Wrapper {
U value;
template<typename Arg>
Wrapper(Arg&& arg)
: value(std::forward<Arg>(arg)) {
}
};
struct Impl : Wrapper<T, I>... {
template<typename Arg> Impl(Arg&& arg)
: Wrapper<T, I>(std::forward<Arg>(arg))... {}
};
template<typename Arg> ConstructTupleI(Arg&& arg)
: impl(std::forward<Arg>(arg)),
value((static_cast<Wrapper<T, I>&>(impl)).value...) {
}
operator type() const { return value; }
ref_type operator()() const { return value; }
Impl impl;
ref_type value;
};
template<typename...T> struct List{};
template<typename L, typename...T> struct WrapNum;
template<typename...TI> struct WrapNum<List<TI...>> {
using type = ConstructTupleI<TI...>;
};
template<typename...TI, typename T, typename...Rest>
struct WrapNum<List<TI...>, T, Rest...>
: WrapNum<List<TI..., Item<T, sizeof...(TI)>>, Rest...> {
};
// Use WrapNum to make ConstructTupleI from ConstructTuple
template<typename...T> using ConstructTuple = typename WrapNum<List<>, T...>::type;
// Finally, a convenience alias in case we want to give `ConstructTuple`
// a tuple type instead of a list of types:
template<typename Tuple> struct ConstructFromTupleHelper;
template<typename...T> struct ConstructFromTupleHelper<std::tuple<T...>> {
using type = ConstructTuple<T...>;
};
template<typename Tuple>
using ConstructFromTuple = typename ConstructFromTupleHelper<Tuple>::type;
With test here.
I believe the only way to manually unroll the definition. Something like the following might work. I welcome attempts to make it nicer though.
#include <iostream>
#include <tuple>
struct A { A(std::istream& is) {}};
struct B { B(std::istream& is) {}};
template <typename... Ts>
class Parser
{ };
template <typename T>
class Parser<T>
{
public:
static std::tuple<T> parse(std::istream& is) {return std::make_tuple(T(is)); }
};
template <typename T, typename... Ts>
class Parser<T, Ts...>
{
public:
static std::tuple<T,Ts...> parse(std::istream& is)
{
A t(is);
return std::tuple_cat(std::tuple<T>(std::move(t)),
Parser<Ts...>::parse(is));
}
};
int main()
{
Parser<A,B>::parse(std::cin);
return 1;
}

How can I iterate over a packed variadic template argument list?

I'm trying to find a method to iterate over an a pack variadic template argument list.
Now as with all iterations, you need some sort of method of knowing how many arguments are in the packed list, and more importantly how to individually get data from a packed argument list.
The general idea is to iterate over the list, store all data of type int into a vector, store all data of type char* into a vector, and store all data of type float, into a vector. During this process there also needs to be a seperate vector that stores individual chars of what order the arguments went in. As an example, when you push_back(a_float), you're also doing a push_back('f') which is simply storing an individual char to know the order of the data. I could also use a std::string here and simply use +=. The vector was just used as an example.
Now the way the thing is designed is the function itself is constructed using a macro, despite the evil intentions, it's required, as this is an experiment. So it's literally impossible to use a recursive call, since the actual implementation that will house all this will be expanded at compile time; and you cannot recruse a macro.
Despite all possible attempts, I'm still stuck at figuring out how to actually do this. So instead I'm using a more convoluted method that involves constructing a type, and passing that type into the varadic template, expanding it inside a vector and then simply iterating that. However I do not want to have to call the function like:
foo(arg(1), arg(2.0f), arg("three");
So the real question is how can I do without such? To give you guys a better understanding of what the code is actually doing, I've pasted the optimistic approach that I'm currently using.
struct any {
void do_i(int e) { INT = e; }
void do_f(float e) { FLOAT = e; }
void do_s(char* e) { STRING = e; }
int INT;
float FLOAT;
char *STRING;
};
template<typename T> struct get { T operator()(const any& t) { return T(); } };
template<> struct get<int> { int operator()(const any& t) { return t.INT; } };
template<> struct get<float> { float operator()(const any& t) { return t.FLOAT; } };
template<> struct get<char*> { char* operator()(const any& t) { return t.STRING; } };
#define def(name) \
template<typename... T> \
auto name (T... argv) -> any { \
std::initializer_list<any> argin = { argv... }; \
std::vector<any> args = argin;
#define get(name,T) get<T>()(args[name])
#define end }
any arg(int a) { any arg; arg.INT = a; return arg; }
any arg(float f) { any arg; arg.FLOAT = f; return arg; }
any arg(char* s) { any arg; arg.STRING = s; return arg; }
I know this is nasty, however it's a pure experiment, and will not be used in production code. It's purely an idea. It could probably be done a better way. But an example of how you would use this system:
def(foo)
int data = get(0, int);
std::cout << data << std::endl;
end
looks a lot like python. it works too, but the only problem is how you call this function.
Heres a quick example:
foo(arg(1000));
I'm required to construct a new any type, which is highly aesthetic, but thats not to say those macros are not either. Aside the point, I just want to the option of doing:
foo(1000);
I know it can be done, I just need some sort of iteration method, or more importantly some std::get method for packed variadic template argument lists. Which I'm sure can be done.
Also to note, I'm well aware that this is not exactly type friendly, as I'm only supporting int,float,char* and thats okay with me. I'm not requiring anything else, and I'll add checks to use type_traits to validate that the arguments passed are indeed the correct ones to produce a compile time error if data is incorrect. This is purely not an issue. I also don't need support for anything other then these POD types.
It would be highly apprecaited if I could get some constructive help, opposed to arguments about my purely illogical and stupid use of macros and POD only types. I'm well aware of how fragile and broken the code is. This is merley an experiment, and I can later rectify issues with non-POD data, and make it more type-safe and useable.
Thanks for your undertstanding, and I'm looking forward to help.
If your inputs are all of the same type, see OMGtechy's great answer.
For mixed-types we can use fold expressions (introduced in c++17) with a callable (in this case, a lambda):
#include <iostream>
template <class ... Ts>
void Foo (Ts && ... inputs)
{
int i = 0;
([&]
{
// Do things in your "loop" lambda
++i;
std::cout << "input " << i << " = " << inputs << std::endl;
} (), ...);
}
int main ()
{
Foo(2, 3, 4u, (int64_t) 9, 'a', 2.3);
}
Live demo
(Thanks to glades for pointing out in the comments that I didn't need to explicitly pass inputs to the lambda. This made it a lot neater.)
If you need return/breaks in your loop, here are some workarounds:
Demo using try/throw. Note that throws can cause tremendous slow down of this function; so only use this option if speed isn't important, or the break/returns are genuinely exceptional.
Demo using variable/if switches.
These latter answers are honestly a code smell, but shows it's general-purpose.
If you want to wrap arguments to any, you can use the following setup. I also made the any class a bit more usable, although it isn't technically an any class.
#include <vector>
#include <iostream>
struct any {
enum type {Int, Float, String};
any(int e) { m_data.INT = e; m_type = Int;}
any(float e) { m_data.FLOAT = e; m_type = Float;}
any(char* e) { m_data.STRING = e; m_type = String;}
type get_type() const { return m_type; }
int get_int() const { return m_data.INT; }
float get_float() const { return m_data.FLOAT; }
char* get_string() const { return m_data.STRING; }
private:
type m_type;
union {
int INT;
float FLOAT;
char *STRING;
} m_data;
};
template <class ...Args>
void foo_imp(const Args&... args)
{
std::vector<any> vec = {args...};
for (unsigned i = 0; i < vec.size(); ++i) {
switch (vec[i].get_type()) {
case any::Int: std::cout << vec[i].get_int() << '\n'; break;
case any::Float: std::cout << vec[i].get_float() << '\n'; break;
case any::String: std::cout << vec[i].get_string() << '\n'; break;
}
}
}
template <class ...Args>
void foo(Args... args)
{
foo_imp(any(args)...); //pass each arg to any constructor, and call foo_imp with resulting any objects
}
int main()
{
char s[] = "Hello";
foo(1, 3.4f, s);
}
It is however possible to write functions to access the nth argument in a variadic template function and to apply a function to each argument, which might be a better way of doing whatever you want to achieve.
Range based for loops are wonderful:
#include <iostream>
#include <any>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p.type().name() << std::endl;
}
}
int main() {
printVariadic(std::any(42), std::any('?'), std::any("C++"));
}
For me, this produces the output:
i
c
PKc
Here's an example without std::any, which might be easier to understand for those not familiar with std::type_info:
#include <iostream>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p << std::endl;
}
}
int main() {
printVariadic(1, 2, 3);
}
As you might expect, this produces:
1
2
3
You can create a container of it by initializing it with your parameter pack between {}. As long as the type of params... is homogeneous or at least convertable to the element type of your container, it will work. (tested with g++ 4.6.1)
#include <array>
template <class... Params>
void f(Params... params) {
std::array<int, sizeof...(params)> list = {params...};
}
This is not how one would typically use Variadic templates, not at all.
Iterations over a variadic pack is not possible, as per the language rules, so you need to turn toward recursion.
class Stock
{
public:
bool isInt(size_t i) { return _indexes.at(i).first == Int; }
int getInt(size_t i) { assert(isInt(i)); return _ints.at(_indexes.at(i).second); }
// push (a)
template <typename... Args>
void push(int i, Args... args) {
_indexes.push_back(std::make_pair(Int, _ints.size()));
_ints.push_back(i);
this->push(args...);
}
// push (b)
template <typename... Args>
void push(float f, Args... args) {
_indexes.push_back(std::make_pair(Float, _floats.size()));
_floats.push_back(f);
this->push(args...);
}
private:
// push (c)
void push() {}
enum Type { Int, Float; };
typedef size_t Index;
std::vector<std::pair<Type,Index>> _indexes;
std::vector<int> _ints;
std::vector<float> _floats;
};
Example (in action), suppose we have Stock stock;:
stock.push(1, 3.2f, 4, 5, 4.2f); is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(3.2f, 4, 5, 4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push(4, 5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push();, which is resolved to (c) as there is no argument, thus ending the recursion
Thus:
Adding another type to handle is as simple as adding another overload, changing the first type (for example, std::string const&)
If a completely different type is passed (say Foo), then no overload can be selected, resulting in a compile-time error.
One caveat: Automatic conversion means a double would select overload (b) and a short would select overload (a). If this is not desired, then SFINAE need be introduced which makes the method slightly more complicated (well, their signatures at least), example:
template <typename T, typename... Args>
typename std::enable_if<is_int<T>::value>::type push(T i, Args... args);
Where is_int would be something like:
template <typename T> struct is_int { static bool constexpr value = false; };
template <> struct is_int<int> { static bool constexpr value = true; };
Another alternative, though, would be to consider a variant type. For example:
typedef boost::variant<int, float, std::string> Variant;
It exists already, with all utilities, it can be stored in a vector, copied, etc... and seems really much like what you need, even though it does not use Variadic Templates.
There is no specific feature for it right now but there are some workarounds you can use.
Using initialization list
One workaround uses the fact, that subexpressions of initialization lists are evaluated in order. int a[] = {get1(), get2()} will execute get1 before executing get2. Maybe fold expressions will come handy for similar techniques in the future. To call do() on every argument, you can do something like this:
template <class... Args>
void doSomething(Args... args) {
int x[] = {args.do()...};
}
However, this will only work when do() is returning an int. You can use the comma operator to support operations which do not return a proper value.
template <class... Args>
void doSomething(Args... args) {
int x[] = {(args.do(), 0)...};
}
To do more complex things, you can put them in another function:
template <class Arg>
void process(Arg arg, int &someOtherData) {
// You can do something with arg here.
}
template <class... Args>
void doSomething(Args... args) {
int someOtherData;
int x[] = {(process(args, someOtherData), 0)...};
}
Note that with generic lambdas (C++14), you can define a function to do this boilerplate for you.
template <class F, class... Args>
void do_for(F f, Args... args) {
int x[] = {(f(args), 0)...};
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
Using recursion
Another possibility is to use recursion. Here is a small example that defines a similar function do_for as above.
template <class F, class First, class... Rest>
void do_for(F f, First first, Rest... rest) {
f(first);
do_for(f, rest...);
}
template <class F>
void do_for(F f) {
// Parameter pack is empty.
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
You can't iterate, but you can recurse over the list. Check the printf() example on wikipedia: http://en.wikipedia.org/wiki/C++0x#Variadic_templates
You can use multiple variadic templates, this is a bit messy, but it works and is easy to understand.
You simply have a function with the variadic template like so:
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
And a helper function like so:
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
Now when you call "function" the "helperFunction" will be called and isolate the first passed parameter from the rest, this variable can b used to call another function (or something). Then "function" will be called again and again until there are no more variables left. Note you might have to declare helperClass before "function".
The final code will look like this:
void helperFunction();
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args);
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
The code is not tested.
#include <iostream>
template <typename Fun>
void iteratePack(const Fun&) {}
template <typename Fun, typename Arg, typename ... Args>
void iteratePack(const Fun &fun, Arg &&arg, Args&& ... args)
{
fun(std::forward<Arg>(arg));
iteratePack(fun, std::forward<Args>(args)...);
}
template <typename ... Args>
void test(const Args& ... args)
{
iteratePack([&](auto &arg)
{
std::cout << arg << std::endl;
},
args...);
}
int main()
{
test(20, "hello", 40);
return 0;
}
Output:
20
hello
40