C++ varadic template function - only one instance of known parameter pack - c++

I want to use a fold expression but the function will only ever be used with one known parameter pack.
i.e.
template <class... Types>
Foo fn_impl(Arg arg) {
// here, a fold expression involving Types... that returns a Foo
}
Foo fn(Arg arg) {
return fn_impl<Bar, Baz>(arg);
}
And that's it, fn_impl won't ever be used again.
Is there a way to make this less verbose?
Ideally, I'd like to write the implementation of fn in its body, without a separate implementation function (which adds noise, imo).
I know I could "unroll" the fold expression with the types in the parameter pack by hand, but in this case, using a fold expression is just very convenient to make the implementation of fn not too verbose.
Here's a complete example, see highlighted QUESTION comment:
#include <cassert>
#include <cstdio>
#include <memory>
struct Base {
virtual ~Base() {}
virtual const char *get_name() const = 0;
};
template <class Derived> struct Base_CRTP : public Base {
const char *get_name() const final {
return static_cast<const Derived *>(this)->name;
}
};
struct A : Base_CRTP<A> {
static constexpr const char *name = "A";
};
struct B : Base_CRTP<B> {
static constexpr const char *name = "B";
};
#define ITest_DERIVED_CLASSES A, B
// QUESTION: Can this be entirely moved into the definition of #1?
template <class IType, class... Types>
std::unique_ptr<IType> make_by_class_index___impl(int class_index) {
int i = 0;
std::unique_ptr<IType> ret;
([&] {
if (i++ == class_index)
ret = std::make_unique<Types>();
return ret != nullptr;
}() ||
...);
return ret;
}
// #1
std::unique_ptr<Base> make_by_class_index(int class_index) {
return make_by_class_index___impl<Base, ITest_DERIVED_CLASSES>(class_index);
}
template <class... Types> void print_pack_names() { (puts(Types::name), ...); }
int main() {
print_pack_names<ITest_DERIVED_CLASSES>();
puts("");
auto p = make_by_class_index(0);
assert(p != nullptr);
printf("p name: %s\n", p->get_name());
auto p2 = make_by_class_index(1);
assert(p2 != nullptr);
printf("p2 name: %s\n", p2->get_name());
auto p3 = make_by_class_index(99);
assert(p3 == nullptr);
}

In lack of sufficient details, let's assume without loss of generality that Arg is int that that Foo, Bar and Baz are defined as follows:
struct Foo { int x; };
struct Bar { static constexpr int foo() { return 1; } };
struct Baz { static constexpr int foo() { return 2; } };
If you may use C++20 you can migrate a) a variadic function which contains a fold expression and b) a call to site to it, e.g.:
template <typename... Types> Foo fn_impl(int arg) {
return { arg + (Types::foo() + ...) };
}
// at call site
fn_impl<Bar, Baz>(arg);
into a single generic immediately invoked lambda, leveraging that P0428R2 (introduced in C++20) allows template heads for generic lambdas:
Foo fn(int arg) {
return []<typename... Types>(int arg) -> Foo {
return { arg + (Types::foo() + ...) };
}
.operator()<Bar, Baz>(arg);
}
This arguably looks quite complex, though, particularly as you need to use the operator name syntax to provide explicit template arguments for the generic lambdas. The separate function approach is arguably easier to follow for future maintainers.

Related

Deduce Function Arguments From A Function Type Declare, For Templated Struct Method?

I was wondering if it was possible to deduce the return type, and parameters from a function type define.
I was hoping to do something similar:
template<class T>
struct _function_wrapper_t
{
[return of T] call([Args of T]....)
{
return (T)m_pfnFunc(Args);
}
void* m_pfnFunc;
};
int MultiplyTwoNumbers(int nNum, int nNum2)
{
return nNum * nNum2;
}
int MultiplyThreeNumbers(int nNum, int nNum2, int* pnNum3)
{
return nNum * nNum2 * *pnNum3;
}
int main()
{
_function_wrapper_t<decltype(&MultiplyTwoNumbers)> two(&MultiplyTwoNumbers);
_function_wrapper_t<decltype(&MultiplyThreeNumbers)> three(&MultiplyThreeNumbers);
auto ret1 = two.call(1, 2);
auto ret2 = three.call(4, 5, 8);
}
However I'm not sure if its possible to discern the return type and function arguments from a type of function pointer.
if you did say
typedef void*(__cdecl* fnOurFunc_t)(const char*, int, float**);
The compiler knows to use that as the type in the future, does the same apply further to templates? This is needed for a VERY specific use case.
Thanks in advance!
The simple solution is to let the compiler deduce return type and let the caller pass the right types (and fail to compile when they don't):
template<class T>
struct _function_wrapper_t
{
template <typename ...U>
auto call(U&&... t)
{
return m_pfnFunc(std::forward<U>(t)...);
}
T m_pfnFunc;
};
If you do not like that you can use partial specialization:
template<class T>
struct _function_wrapper_t;
template <typename R,typename...Args>
struct _function_wrapper_t<R(*)(Args...)>
{
R call(Args...args)
{
return m_pfnFunc(args...);
}
using f_type = R(*)(Args...);
f_type m_pfnFunc;
};
Live Demo
PS: perfect forwarding is also possible in the latter case but it requires some boilerplate that I left out for the sake of brevity.
Check the std::function implementation. It seems it does what you need:
#include <functional>
int MultiplyTwoNumbers(int nNum, int nNum2)
{
return nNum * nNum2;
}
int MultiplyThreeNumbers(int nNum, int nNum2, int pnNum3)
{
return nNum * nNum2 * pnNum3;
}
int main()
{
std::function<decltype(MultiplyTwoNumbers)> two = &MultiplyTwoNumbers;
std::function<decltype(MultiplyThreeNumbers)> three = &MultiplyThreeNumbers;
auto ret1 = two(1, 2);
auto ret2 = three(4, 5, 8);
}

Is this legal template lambda syntax?

While refactoring some legacy code, I came across this traditional implementation of a predicate to be used in STL algorithms:
template<bool b>
struct StructPred {
bool operator()(S const & s) { return s.b == b; }
};
I was tired and hitting the Ballmer Peak, so I accidentally rewrote it into a lambda like this, which seemed natural and also worked:
template<bool b>
auto lambda_pred = [] (S const & s) { return s.b == b; };
Later I realized that I've never seen a template lambda like this. I couldn't find anything similar on cppreference or on stackoverflow. The canonical way of producing template lambdas seems to be wrapping them in template structs or template functions. C++20 introduces named template params for lambdas, but that's a different syntax (after the capture brackets).
Now my questions are: Is this legal syntax? Is it documented anywhere? Is it even a lambda or something else? Are there any implications or side effects as compared to the wrapper alternatives? Why does everybody recommend wrapper implementations when this works? Am I missing something obvious?
Full working test code below and at godbolt. Just to be sure I also added a type template parameter version. MSVC, GCC and clang are happy with this code.
#include <vector>
#include <algorithm>
struct S {
bool b = false;
};
// classic function object
template<bool b>
struct StructPred {
bool operator()(S const & s) { return s.b == b; }
};
// template function producing a lambda
template<bool b>
auto make_pred() {
return [] (S const & s) { return s.b == b; };
}
// direct template lambda
template<bool b>
auto lambda_pred = [] (S const & s) { return s.b == b; };
// also with type params
template<typename T, bool b>
auto lambda_pred_t = [] (T const & t) { return t.b == b; };
std::pair<size_t, size_t> count1(std::vector<S> const & v) {
return {
std::count_if(v.begin(), v.end(), StructPred<true>{}),
std::count_if(v.begin(), v.end(), StructPred<false>{})
};
}
std::pair<size_t, size_t> count2(std::vector<S> const & v) {
return {
std::count_if(v.begin(), v.end(), make_pred<true>()),
std::count_if(v.begin(), v.end(), make_pred<false>())
};
}
std::pair<size_t, size_t> count3(std::vector<S> const & v) {
return {
std::count_if(v.begin(), v.end(), lambda_pred<true>),
std::count_if(v.begin(), v.end(), lambda_pred<false>)
};
}
std::pair<size_t, size_t> count4(std::vector<S> const & v) {
return {
std::count_if(v.begin(), v.end(), lambda_pred_t<S, true>),
std::count_if(v.begin(), v.end(), lambda_pred_t<S, false>)
};
}
void test() {
std::vector<S> v{3};
v[1].b = true;
// all implementations correctly return {1,2}
auto c1 = count1(v);
auto c2 = count2(v);
auto c3 = count3(v);
auto c4 = count4(v);
}
template<bool b>
auto lambda_pred = [] (S const & s) { return s.b == b; };
This is not really a template-lambda, it is rather a variable template which is assigned to a lambda.
It is not equivalent to adding template parameters to the implicitly declared Closure struct which has this lambda as a call operator (the traditional approach):
template<bool b>
struct StructPred { // NOT equivalent to this
bool operator()(S const & s) { return s.b == b; }
};
struct StructPred { // NOT equivalent to this either
template<bool b>
bool operator()(S const & s) { return s.b == b; }
};
It is instead equivalent to creating different Closures depending on the template parameters of the variable. So for the bool example, this would be like choosing between the operator() of one of the following types:
struct StructPred_true {
bool operator()(S const & s) { return s.b == true; }
}
struct StructPred_false {
bool operator()(S const & s) { return s.b == false; }
}
This approach won't allow for partial specializations and is thus less powerful.
Another reason why this approach might be unpopular is that it doesn't give you easy access to the Closure type(s).
StructPred can be worked with explicitly, unlike the anonymous classes StructPred_true and StructPred_false
A template lambda in C++20 would look as follows:
auto lambda = []<bool b>(S const & s){ return s.b == b; };
This is instead equivalent to making the Closure's operator() templated.
All standard references below refers to N4659: March 2017 post-Kona working draft/C++17 DIS.
Generic lambdas: a C++14 feature
The canonical way of producing template lambdas seems to be wrapping them in template structs or template functions. C++20 introduces named template params for lambdas, but that's a different syntax (after the capture brackets).
The other answer thoroughly explains what construct the OPs variable template is, whereas this answer addresses the emphasized segment above; namely that generic lambdas is a language feature as of C++14, and not something that is available only as of C++20.
As per [expr.prim.lambda.closure]/3 [extract]:
[...] For a generic lambda, the closure type has a public inline function call operator member template whose template-parameter-list consists of one invented type template-parameter for each occurrence of auto in the lambda's parameter-declaration-clause, in order of appearance. [...]
a generic lambda can be declared as
auto glambda = [](auto a, auto b) { return a < b; };
which is comparable to
struct anon_struct {
template<typename T, typename U>
bool operator()(T a, U b) { return a < b; }
}
and not
template<typename T, typename U>
struct anon_struct {
bool operator()(T a, U b) { return a < b; }
}
which is essential as a single generic lambda object (whose closure type is in fact not a class template but a non-template (non-union) class) can be used to generically invoke its function call operator template for different instantiations of its invented template parameters.
#include <iostream>
#include <ios>
int main() {
auto gl = [](auto a, auto b) { return a < b; };
std::cout << std::boolalpha
<< gl(1, 2) << " " // true ("<int, int>")
<< gl(3.4, 2.2) << " " // false ("<double, double>")
<< gl(98, 'a'); // false ("<int, char>")
}
Generic lambdas with an explicit template parameter list: a C++20 feature
As of C++20 we may use an explicit template parameter list when declaring the generic lambdas, as well as offering a sugared syntax for providing explicit template arguments when invoking the generic lambdas.
In C++14 and C++17 the template parameters for a generic lambda can only be declared implicitly as invented type template parameters for each declared auto parameter in the lambda declaration, which has the restrictions that:
the invented template parameters can only be type template parameters synthesized (as shown above), and
the type template parameters cannot be directly accessed in the body of the lambda, but needs to be extracted using decltype on the respective auto parameter.
Or, as shown with a contrived example:
#include <type_traits>
// C++17 (C++14 if we remove constexpr
// and use of _v alias template).
auto constexpr cpp17_glambda =
// Template parameters cannot be declared
// explicitly, meaning only type template
// parameters can be used.
[](auto a, auto b)
// Inventend type template parameters cannot
// be accessed/used directly.
-> std::enable_if_t<
std::is_base_of_v<decltype(a), decltype(b)>> {};
struct Base {};
struct Derived : public Base {};
struct NonDerived {};
struct ConvertsToDerived { operator Derived() { return {}; } };
int main() {
cpp17_glambda(Base{}, Derived{}); // Ok.
//cpp17_glambda(Base{}, NonDerived{}); // Error.
// Error: second invented type template parameter
// inferred to 'ConvertsToDerived'.
//cpp17_glambda(Base{}, ConvertsToDerived{});
// OK: explicitly specify the types of the invented
// type template parameters.
cpp17_glambda.operator()<Base, Derived>(
Base{}, ConvertsToDerived{});
}
Now, in C++20, with the introduction of name template parameters for lambdas (as well as requires clauses), the example above can be reduced to:
#include <type_traits>
auto constexpr cpp20_glambda =
[]<typename T, typename U>(T, U)
requires std::is_base_of_v<T, U> { };
struct Base {};
struct Derived : public Base {};
struct NonDerived {};
struct ConvertsToDerived { operator Derived() { return {}; } };
int main() {
cpp20_glambda(Base{}, Derived{}); // Ok.
//cpp20_glambda(Base{}, NonDerived{}); // Error.
// Error: second type template parameter
// inferred to 'ConvertsToDerived'.
//cpp20_glambda(Base{}, ConvertsToDerived{});
// OK: explicitly specify the types of the
// type template parameters.
cpp20_glambda.operator()<Base, Derived>(
Base{}, ConvertsToDerived{});
}
and we can moreover declare lambdas with template parameters that are not necessarily type template parameters:
#include <iostream>
#include <ios>
template<typename T>
struct is_bool_trait {
static constexpr bool value = false;
};
template<>
struct is_bool_trait<bool> {
static constexpr bool value = true;
};
template<typename T>
struct always_true_trait {
static constexpr bool value = true;
};
int main() {
auto lambda = []<
template<typename> class TT = is_bool_trait>(auto a) -> bool {
if constexpr (!TT<decltype(a)>::value) {
return true; // default for non-bool.
}
return a;
};
std::cout << std::boolalpha
<< lambda(false) << " " // false
<< lambda(true) << " " // true
<< lambda(0) << " " // true
<< lambda(1) << " " // true
<< lambda.operator()<always_true_trait>(0) << " " // false
<< lambda.operator()<always_true_trait>(1); // true
}

Return different types with different template parameter value (but same type)

What I want to do is to define 3 functions like these:
template<int t = 0> int test() { return 8; }
template<int t = 1> float test() { return 8.8; }
template<int t = 2> std::string test() { return "8.9"; }
int main()
{
int a = test<0>();
float b = test<1>();
std::string c = test<2>();
return 0;
}
They use the same type of template parameter but return different types.
I believe there must be some way to do that (like std::get<>() does it), but I can not find how to do it.
It looks to me like you are after function template specialization. Needing to provide a different implementation for each of the calls fits the bill. There is however one caveat, and it's that a specialization may not alter the signature of the primary template being specialized, only the implementation. This means we cannot do e.g.
template<int t> int test(); // Primary
template<> int test<0>() { return 8; } // OK, signature matches
template<> float test<1>() { return 8.8; } // ERROR
But we are not toasted yet. The signature of the specialization has to match the one that primary will get for a specific argument. So if we make the return type dependent on the template parameter, and resolve to the correct type, we could define our specialization just fine.
template<int t> auto test() -> /* Magic involving t that resolves to int, float, string */;
template<> int test<0>() { return 8; }
template<> float test<1>() { return 8.8; }
template<> std::string test<2>() { return "8.9"; }
Does something like that exist? Yes, and you hinted at it. We can use std::tuple. It has a std::tuple_element utility that can map an integer to one of a type sequence (the tuple's elements). With a little helper, we can construct our code to work the way you wish:
using types = std::tuple<int, float, std::string>;
template<int t> auto test() -> std::tuple_element_t<t, types>;
template<> int test<0>() { return 8; }
template<> float test<1>() { return 8.8; }
template<> std::string test<2>() { return "8.9"; }
Now every specialization matches the signature the primary would end up with. And so we get an approval from our compiler.
See it live
The #StoryTeller and #formerlyknownas_463035818 have provided a well-explained template specialization way of doing it. Alternatively, one can combine the three functions to one single function using if-constexpr and with a decltype(auto) return in c++17.
#include <iostream>
#include <string>
#include <cstring>
using namespace std::literals;
template<int t>
constexpr decltype(auto) test() noexcept
{
if constexpr (t == 0) return 8;
else if constexpr (t == 1) return 8.8f;
else if constexpr (t == 2) return "8.9"s;
}
(See live online)
You declared the same template 3 times, while you actually want specialisations. As far as I know you cannot specialize on return type directly (*). However, there is nothing that cannot be solved with an additional layer of indirection. You can do something along the line of:
#include <string>
template <int> struct return_type_tag {};
template <> struct return_type_tag<0> { using type = int; };
template <> struct return_type_tag<1> { using type = float; };
template <> struct return_type_tag<2> { using type = std::string; };
template <int x> typename return_type_tag<x>::type test();
template<> int test<0>() { return 8; }
template<> float test<1>() { return 8.8; }
template<> std::string test<2>() { return "8.9"; }
int main()
{
int a = test<0>();
float b = test<1>();
std::string c = test<2>();
return 0;
}
(*) actually you can, with a small trick, see this answer. The only benefit of my approach is that it already worked pre-c++11.

std::optional::value_or() - lazy argument evaluation

Is it possible to evaluate std::optional::value_or(expr) argument in a lazy way, so the expr were calculated only in the case of having no value?
If not, what would be a proper replacement?
#include <optional>
template <typename F>
struct Lazy
{
F f;
operator decltype(f())() const
{
return f();
}
};
template <typename F>
Lazy(F f) -> Lazy<F>;
int main()
{
std::optional<int> o;
int i = o.value_or(Lazy{[]{return 0;}});
}
DEMO
You may write your helper function:
template<typename T, typename F>
T lazy_value_or(const std::optional<T> &opt, F fn) {
if(opt) return opt.value();
return fn();
}
which can then be used as:
T t = lazy_value_or(opt, [] { return expensive_computation();});
If that's significantly less typing than doing it explicitly that's up to you to judge; still, you can make it shorter with a macro:
#define LAZY_VALUE_OR(opt, expr) \
lazy_value_or((opt), [&] { return (expr);})
to be used as
T t = LAZY_VALUE_OR(opt, expensive_calculation());
This is closest to what I think you want, but may be frowned upon as it hides a bit too much stuff.
Make an optional of function type.
Then a lambda can be passed in, which when called will calculate the correct value at the requested moment.
std::optional<std::function<int()>> opt;
int a = 42;
opt = [=] { return a; }
int b = 4;
int c = opt.value_or([=] { return b * 10 + 2;}) ();

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