How to retrieve variadic template parameters without auxillary function template?Storing C++ template function definitions in a .CPP fileUse 'class' or 'typename' for template parameters?Why not infer template parameter from constructor?Partial specialization of variadic templatesVariadic templates without function parametersEasiest way to get the N-th argument of a variadic templated class?Forcing variadic template member function instantiation in classError deducing variadic function templateC++ variadic template template argument that matches any kind of parametersC++ async with variadic template can not find correct function template specialization

On what legal basis did the UK remove the 'European Union' from its passport?

Extracting sublists that contain similar elements

Make all the squares explode

On studying Computer Science vs. Software Engineering to become a proficient coder

Was this a power play by Daenerys?

51% attack - apparently very easy? refering to CZ's "rollback btc chain" - How to make sure such corruptible scenario can never happen so easily?

How can I answer high-school writing prompts without sounding weird and fake?

What stroke width Instagram is using for its icons and how to get same results?

Would an 8% reduction in drag outweigh the weight addition from this custom CFD-tested winglet?

Is the schwa sound consistent?

Who was this character from the Tomb of Annihilation adventure before they became a monster?

Front derailleur hard to move due to gear cable angle

What does the expression "right on the tip of my tongue" mean?

How does noise-cancellation work in Mac laptops?

Extrude the faces of a cube symmetrically along XYZ

What happens if a creature that would fight isn't on the battlefield anymore?

Why was castling bad for white in this game, and engine strongly prefered trading queens?

What's the word for the soldier salute?

Why was the Ancient One so hesitant to teach Dr. Strange the art of sorcery?

Why in a Ethernet LAN, a packet sniffer can obtain all packets sent over the LAN?

How many are the non-negative integer solutions of 𝑥 + 𝑦 + 𝑤 + 𝑧 = 16 where x < y?

A curve pass via points at TiKz

What food production methods would allow a metropolis like New York to become self sufficient

How can dragons propel their breath attacks to a long distance



How to retrieve variadic template parameters without auxillary function template?


Storing C++ template function definitions in a .CPP fileUse 'class' or 'typename' for template parameters?Why not infer template parameter from constructor?Partial specialization of variadic templatesVariadic templates without function parametersEasiest way to get the N-th argument of a variadic templated class?Forcing variadic template member function instantiation in classError deducing variadic function templateC++ variadic template template argument that matches any kind of parametersC++ async with variadic template can not find correct function template specialization






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








14















Suppose I have



template<int ...>
struct Ints ;

class MyClass

public:
Ints<1, 2, 3> get() return Ints<1, 2, 3>();
;


What I want to do is simple.



template <class T>
vector<int> MyFunc1(T& x)

Ints<S...> result = x.get();
vector<int> t = S... ;
return t;



Somewhat like this. (Here MyClass can be one example of T.) Apparently, for compiler S... seems to invalid.



template <class T, int... S>
vector<int> MyFunc2(T& x)

Ints<S...> result = x.get();
vector<int> t = S... ;
return t;



This doesn't work either. I think from get() the S... becomes specific and automatically deducible, but compiler doesn't recognize it. (I'm not sure but C++ doesn't deduce template parameters looking inside the function, but only arguments and return type)



The only way I've found is to use another function that finds out what int... was.



template <int ...S>
vector<int> temp(Ints<S...> not_used)

return S... ;


template <class T>
vector<int> MyFunc3(T& x)

auto result = x.get();
return temp(result);



It works well, but requires another extra helper function that does nothing but just provides syntactically clear way to match the S... using templates.



I really want to do this just in single function. Do I really have to define auxiliary function whenever I want to retrieve parameter packs, in every time?



Edit : Ints and MyFunc are just toy example. I want to know general method to retrieve template parameters!










share|improve this question
























  • "Do I really have to define auxiliary function..." Why is it a problem? What do you want to do with the template parameters? Do you want to do the same with them, or different? If the same, maybe you can have a "more templated" temp, so there would be only one auxiliary function needed. If different, then it shouldn't be a real problem that you'll need more temp template functions.

    – geza
    May 2 at 7:35











  • @geza My question is why c++ doesn't provide convenient way of pattern matching, but only making possible in function arguments. temp is perfectly fine, but the problem is that temp is doing nothing but just providing another templates to match int.... (making into vector is just a example of particular job. It may be passed by std::function or whatever, so doesn't even matter)

    – i.stav
    May 2 at 7:51












  • I think that you can use a lamba for this purpose as well. Development of C++ can be influenced by proposals, if you have a great idea, just make one, and submit it.

    – geza
    May 2 at 7:54

















14















Suppose I have



template<int ...>
struct Ints ;

class MyClass

public:
Ints<1, 2, 3> get() return Ints<1, 2, 3>();
;


What I want to do is simple.



template <class T>
vector<int> MyFunc1(T& x)

Ints<S...> result = x.get();
vector<int> t = S... ;
return t;



Somewhat like this. (Here MyClass can be one example of T.) Apparently, for compiler S... seems to invalid.



template <class T, int... S>
vector<int> MyFunc2(T& x)

Ints<S...> result = x.get();
vector<int> t = S... ;
return t;



This doesn't work either. I think from get() the S... becomes specific and automatically deducible, but compiler doesn't recognize it. (I'm not sure but C++ doesn't deduce template parameters looking inside the function, but only arguments and return type)



The only way I've found is to use another function that finds out what int... was.



template <int ...S>
vector<int> temp(Ints<S...> not_used)

return S... ;


template <class T>
vector<int> MyFunc3(T& x)

auto result = x.get();
return temp(result);



It works well, but requires another extra helper function that does nothing but just provides syntactically clear way to match the S... using templates.



I really want to do this just in single function. Do I really have to define auxiliary function whenever I want to retrieve parameter packs, in every time?



Edit : Ints and MyFunc are just toy example. I want to know general method to retrieve template parameters!










share|improve this question
























  • "Do I really have to define auxiliary function..." Why is it a problem? What do you want to do with the template parameters? Do you want to do the same with them, or different? If the same, maybe you can have a "more templated" temp, so there would be only one auxiliary function needed. If different, then it shouldn't be a real problem that you'll need more temp template functions.

    – geza
    May 2 at 7:35











  • @geza My question is why c++ doesn't provide convenient way of pattern matching, but only making possible in function arguments. temp is perfectly fine, but the problem is that temp is doing nothing but just providing another templates to match int.... (making into vector is just a example of particular job. It may be passed by std::function or whatever, so doesn't even matter)

    – i.stav
    May 2 at 7:51












  • I think that you can use a lamba for this purpose as well. Development of C++ can be influenced by proposals, if you have a great idea, just make one, and submit it.

    – geza
    May 2 at 7:54













14












14








14


2






Suppose I have



template<int ...>
struct Ints ;

class MyClass

public:
Ints<1, 2, 3> get() return Ints<1, 2, 3>();
;


What I want to do is simple.



template <class T>
vector<int> MyFunc1(T& x)

Ints<S...> result = x.get();
vector<int> t = S... ;
return t;



Somewhat like this. (Here MyClass can be one example of T.) Apparently, for compiler S... seems to invalid.



template <class T, int... S>
vector<int> MyFunc2(T& x)

Ints<S...> result = x.get();
vector<int> t = S... ;
return t;



This doesn't work either. I think from get() the S... becomes specific and automatically deducible, but compiler doesn't recognize it. (I'm not sure but C++ doesn't deduce template parameters looking inside the function, but only arguments and return type)



The only way I've found is to use another function that finds out what int... was.



template <int ...S>
vector<int> temp(Ints<S...> not_used)

return S... ;


template <class T>
vector<int> MyFunc3(T& x)

auto result = x.get();
return temp(result);



It works well, but requires another extra helper function that does nothing but just provides syntactically clear way to match the S... using templates.



I really want to do this just in single function. Do I really have to define auxiliary function whenever I want to retrieve parameter packs, in every time?



Edit : Ints and MyFunc are just toy example. I want to know general method to retrieve template parameters!










share|improve this question
















Suppose I have



template<int ...>
struct Ints ;

class MyClass

public:
Ints<1, 2, 3> get() return Ints<1, 2, 3>();
;


What I want to do is simple.



template <class T>
vector<int> MyFunc1(T& x)

Ints<S...> result = x.get();
vector<int> t = S... ;
return t;



Somewhat like this. (Here MyClass can be one example of T.) Apparently, for compiler S... seems to invalid.



template <class T, int... S>
vector<int> MyFunc2(T& x)

Ints<S...> result = x.get();
vector<int> t = S... ;
return t;



This doesn't work either. I think from get() the S... becomes specific and automatically deducible, but compiler doesn't recognize it. (I'm not sure but C++ doesn't deduce template parameters looking inside the function, but only arguments and return type)



The only way I've found is to use another function that finds out what int... was.



template <int ...S>
vector<int> temp(Ints<S...> not_used)

return S... ;


template <class T>
vector<int> MyFunc3(T& x)

auto result = x.get();
return temp(result);



It works well, but requires another extra helper function that does nothing but just provides syntactically clear way to match the S... using templates.



I really want to do this just in single function. Do I really have to define auxiliary function whenever I want to retrieve parameter packs, in every time?



Edit : Ints and MyFunc are just toy example. I want to know general method to retrieve template parameters!







c++ templates variadic-templates






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited May 2 at 21:32









J. Antonio Perez

4,291926




4,291926










asked May 2 at 6:42









i.stavi.stav

10316




10316












  • "Do I really have to define auxiliary function..." Why is it a problem? What do you want to do with the template parameters? Do you want to do the same with them, or different? If the same, maybe you can have a "more templated" temp, so there would be only one auxiliary function needed. If different, then it shouldn't be a real problem that you'll need more temp template functions.

    – geza
    May 2 at 7:35











  • @geza My question is why c++ doesn't provide convenient way of pattern matching, but only making possible in function arguments. temp is perfectly fine, but the problem is that temp is doing nothing but just providing another templates to match int.... (making into vector is just a example of particular job. It may be passed by std::function or whatever, so doesn't even matter)

    – i.stav
    May 2 at 7:51












  • I think that you can use a lamba for this purpose as well. Development of C++ can be influenced by proposals, if you have a great idea, just make one, and submit it.

    – geza
    May 2 at 7:54

















  • "Do I really have to define auxiliary function..." Why is it a problem? What do you want to do with the template parameters? Do you want to do the same with them, or different? If the same, maybe you can have a "more templated" temp, so there would be only one auxiliary function needed. If different, then it shouldn't be a real problem that you'll need more temp template functions.

    – geza
    May 2 at 7:35











  • @geza My question is why c++ doesn't provide convenient way of pattern matching, but only making possible in function arguments. temp is perfectly fine, but the problem is that temp is doing nothing but just providing another templates to match int.... (making into vector is just a example of particular job. It may be passed by std::function or whatever, so doesn't even matter)

    – i.stav
    May 2 at 7:51












  • I think that you can use a lamba for this purpose as well. Development of C++ can be influenced by proposals, if you have a great idea, just make one, and submit it.

    – geza
    May 2 at 7:54
















"Do I really have to define auxiliary function..." Why is it a problem? What do you want to do with the template parameters? Do you want to do the same with them, or different? If the same, maybe you can have a "more templated" temp, so there would be only one auxiliary function needed. If different, then it shouldn't be a real problem that you'll need more temp template functions.

– geza
May 2 at 7:35





"Do I really have to define auxiliary function..." Why is it a problem? What do you want to do with the template parameters? Do you want to do the same with them, or different? If the same, maybe you can have a "more templated" temp, so there would be only one auxiliary function needed. If different, then it shouldn't be a real problem that you'll need more temp template functions.

– geza
May 2 at 7:35













@geza My question is why c++ doesn't provide convenient way of pattern matching, but only making possible in function arguments. temp is perfectly fine, but the problem is that temp is doing nothing but just providing another templates to match int.... (making into vector is just a example of particular job. It may be passed by std::function or whatever, so doesn't even matter)

– i.stav
May 2 at 7:51






@geza My question is why c++ doesn't provide convenient way of pattern matching, but only making possible in function arguments. temp is perfectly fine, but the problem is that temp is doing nothing but just providing another templates to match int.... (making into vector is just a example of particular job. It may be passed by std::function or whatever, so doesn't even matter)

– i.stav
May 2 at 7:51














I think that you can use a lamba for this purpose as well. Development of C++ can be influenced by proposals, if you have a great idea, just make one, and submit it.

– geza
May 2 at 7:54





I think that you can use a lamba for this purpose as well. Development of C++ can be influenced by proposals, if you have a great idea, just make one, and submit it.

– geza
May 2 at 7:54












4 Answers
4






active

oldest

votes


















7














What would the ideal interface look like?



If given a variable of type Ints<S...>, we'd ideally be able to use S... with as little modification as possible.



In this case, we can design an interface which allows us to use the parameter pack as an input to a variadic function or lambda, even going so far as to reuse the values as template parameters.



Proposed interface [Dynamic case / ints passed as values]



Both the static case and the dynamic case have similar interfaces, however the dynamic case is slightly cleaner, and makes for a better introduction. Given the variable and a function, we apply the function with the parameter pack contained in the definition of the variable.



Ints<1, 2, 3> ints;

// Get a vector from ints
// vec = 1, 2, 3
auto vec = ints | [](auto... S) return std::vector S...; ;

// Get an array from ints
// arr = 1, 2, 3
auto arr = ints | [](auto... S) return std::array S...; ;

// Get a tuple from ints
// tup = 1, 2, 3
auto tup = ints | [](auto... S) return std::make_tuple(S...); ;

// Get sum of ints using a fold expression
auto sum = ints | [](auto... S) return (S + ...); ;


It's a simple, unified syntax which allows us to take S and use it as a parameter pack.



Writing this interface



This part is pretty straight-forward too. We take a variable of type Ints<S...>, and a function, and apply the function with S....



template<int... S, class Func>
auto operator|(Ints<S...>, Func&& f)
return f(S...);



Proposed interface [Static case / ints usable as template parameters]



As stated before, the static case has a similar interface to the dynamic case, and it won't be too much of a stretch conceptually. From a user standpoint, the only difference is that instead of using S... as the parameter pack, well useS.value...` as the pack.



For each value, we want to encapsulate it in a corresponding type templated on the value. This allows us to access it in a constexpr context.



template<int Value>
struct ConstInt
constexpr static int value = Value;
;


To differentiate it from the dynamic case, I'm going to overload / instead of |. Otherwise, they behave similarly. The implementation is pretty much the same as the dynamic case, except that the values are wrapped in the ConstInt class, and each will have it's own type.



template<int... S, class F>
auto operator/(Ints<S...>, F&& func)
return func(ConstInt<S>()...);



Using this interface statically



C++ allows us to access static members of a class using the same syntax as non-static members, without losing constexpr status.



Let's say I have some ConstInt with a value of 10. I can directly use I.value as a template parameter, or I can use decltype(I)::value:



// This is what'll be passed in as a parameter
ConstInt<10> I;

std::array<int, I.value> arr1;
std::array<int, decltype(I)::value> arr2;
// Both have length 10


Expanding a parameter pack is therefore extraordinarily straight-forward, and it ends up being almost identical to the dynamic case, the only difference being the .value appended to S. Shown below are the examples from the dynamic case, this time using the static case syntax:



Ints<1, 2, 3> ints;

// Get a vector from ints
auto vec = ints | [](auto... S) return std::vector S.value...; ;

// Get an array from ints
// arr = 1, 2, 3
auto arr = ints | [](auto... S) return std::array S.value...; ;

// Get a tuple from ints
auto tup = ints | [](auto... S) return std::make_tuple(S.value...); ;

// Get sum of ints using a fold expression
auto sum = ints | [](auto... S) return (S.value + ...); ;


So what's new? Because value is constexpr, S.value can be used trivially as a template parameter. In this example, we use S.value to index into a tuple using std::get:



auto tupA = std::make_tuple(10.0, "Hello", 3); 

auto indicies = Ints<2, 0, 1>;

// tupB = 3, 10.0, "Hello"
auto tupB = indicies / [&](auto... S)
return std::make_tuple(std::get<S.value>(tupA)...);
;


And in this example, we square every element in a sequence, and return a new sequence:



auto ints = Ints<0, 1, 2, 3, 4, 5>(); 

// ints_squared = Ints<0, 1, 4, 9, 16, 25>();
auto ints_squared = ints / [](auto... S)
return Ints<(S.value * S.value)...>();
;


Alternative solution that avoids operator overloading



If you want to avoid operator overloading, we can take some inspiration from functional programming and handle things with an unpack function, written like so:



template<int... vals>
auto unpack(Ints<vals...>)
return [](auto&& f) return f(vals...); ;


// Static case
template<int... vals>
auto unpack_static(Ints<vals...>)
return [](auto&& f) return f(ConstInt<vals>()...); ;



So what is unpack? This function takes a bunch of values, and it returns a function which takes another function and applies the function with the vals as inputs.



The unpack function allows us to apply those values to a different function, as parameters.



We can assign the result to a variable called apply_ints, and then we can use apply_ints to handle all the specific use-cases:



Ints<1, 2, 3> ints; //this variable has our ints

auto apply_ints = unpack(ints); // We use this function to unpack them


We can re-write the examples from before, this time using apply_ints:



// Get a vector from ints
// vec = 1, 2, 3
auto vec = apply_ints([](auto... S) return std::vector S...; );

// Get an array from ints
// arr = 1, 2, 3
auto arr = apply_ints([](auto... S) return std::array S...; );

// Get a tuple from ints
// tup = 1, 2, 3
auto tup = apply_ints([](auto... S) return std::make_tuple(S...); );

// Get sum of ints using a fold expression
auto sum = apply_ints([](auto... S) return (S + ...); );


Appendix



This appendix gives a brief overview showing how to use this syntax more generally (such as when working with multiple separate parameter packs).



Bonus example: pairing up values from two separate packs



To give you a better idea of the flexibility of this interface, here's an example where we use it to pair up values from two separate packs.



Ints<1, 2, 3> intsA;
Ints<10, 20, 30> intsB;

// pairs = 1, 10, 2, 20, 3, 30
auto pairs = intsA | [&](auto... S1) [&](auto... S2)
return std::vector std::pairS1, S2... ;
;
;


NB: MSVC and GCC both compile this example without issues, however clang chokes up on it. I assume MSVC and GCC are correct, but I don't know for sure.



Bonus example: Getting a 2-dimensional times table



This example is a little more complicated, but we can also create 2-dimensional arrays of values that draw from all combinations of values from separate packs.



In this case, I use it to create a times table.



Ints<1, 2, 3, 4, 5, 6, 7, 8, 9> digits;

auto multiply = [](auto mul, auto... vals)
return std::vector(mul * vals)...;
;

auto times_table = digits | [&](auto... S1) [&](auto... S2)
return std::vector multiply(S1, S2...)... ;
;
;





share|improve this answer

























  • This would have been a really great answer in some other context - but the OP is specificly trying to avoid auxilery functions... so it's simply too complicated a solution for what is needed.

    – darune
    May 2 at 7:46






  • 1





    @darune: there is only one aux function, which is generic enough to be not a problem (i.e., there is no need to have one additional aux function for each use)

    – geza
    May 2 at 7:49






  • 1





    This really can be made into an immediately invoked lambda expression if OP wants to use it only in one place.

    – YSC
    May 2 at 7:50











  • IMO it's still shooting (way) above the target. you have just created a generalized function instead - and requires now a more convoluted way to create+apply the lambda function. While this can be great, IMO it is shooting above the target and not what OP is asking for !

    – darune
    May 2 at 8:02












  • I added an alternative solution that doesn't involve the creation of an apply_ints helper function, and looks more elegant

    – J. Antonio Perez
    May 2 at 8:11


















6














In C++2a, you might use templated lambda to define your helper inside your function, something like:



auto v = []<std::size_t...Is>(std::index_sequence<Is...>)return std::vectorIs...;(seq);
// ^^^^^^^^^^^^^^^^^^ New in C++2a


Demo






share|improve this answer























  • Thanks. This seems to be very simple way of doing inside-function pattern matching

    – i.stav
    May 2 at 8:40












  • It mostly equivalent to functor with template <std::size_t...Is> auto operator()(std::index_sequence<Is...>) const;.

    – Jarod42
    May 2 at 8:44


















1














I would suggest adding functions to the struct Int to get different representations



#include <vector>
#include <array>

template<int ...values>
struct Ints
auto getAsVector() const
return std::vector<int>( values... );


constexpr auto getAsArray() const
return std::array<int, sizeof...(values)>( values... );

;

class MyClass

public:
Ints<1, 2, 3> get() return Ints<1, 2, 3>();
;

int main()
MyClass a;
auto array = a.get().getAsVector();
return array.size();







share|improve this answer


















  • 1





    Nope. Making into vector is just for explain. Ints and MyFunc is toy example. I don't even want to do that. I'm asking general solution

    – i.stav
    May 2 at 7:09












  • @i.stav There is no truly general solution. You have to use helper functions/classes, but you can try to make those helpers as general as possible (e.g. you could pass container as template <typename> typename> template parameter to them).

    – HolyBlackCat
    May 2 at 7:21












  • @HolyBlackCat Ok thanks, but what I really wonder is like this : why doesn't c++ provide simple and clear way like MyFunc2? Why isn't pattern matching available inside the function?

    – i.stav
    May 2 at 7:26


















1














If you don't use/create a helper template, you need some other way to provide the values.



The most simple, canonical and general way I can think of, is to put them in that same class scope, so that your Ints struct becomes:



template<int ...ints>
struct Ints
constexpr static std::initializer_list<int> vals = ints...;
;


Since it is constexpr it should be evaluated at compile time and not incur a runtime cost.
Now you will be able do something like:



return std::vector<int>(ints.vals);





share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55946950%2fhow-to-retrieve-variadic-template-parameters-without-auxillary-function-template%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    7














    What would the ideal interface look like?



    If given a variable of type Ints<S...>, we'd ideally be able to use S... with as little modification as possible.



    In this case, we can design an interface which allows us to use the parameter pack as an input to a variadic function or lambda, even going so far as to reuse the values as template parameters.



    Proposed interface [Dynamic case / ints passed as values]



    Both the static case and the dynamic case have similar interfaces, however the dynamic case is slightly cleaner, and makes for a better introduction. Given the variable and a function, we apply the function with the parameter pack contained in the definition of the variable.



    Ints<1, 2, 3> ints;

    // Get a vector from ints
    // vec = 1, 2, 3
    auto vec = ints | [](auto... S) return std::vector S...; ;

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = ints | [](auto... S) return std::array S...; ;

    // Get a tuple from ints
    // tup = 1, 2, 3
    auto tup = ints | [](auto... S) return std::make_tuple(S...); ;

    // Get sum of ints using a fold expression
    auto sum = ints | [](auto... S) return (S + ...); ;


    It's a simple, unified syntax which allows us to take S and use it as a parameter pack.



    Writing this interface



    This part is pretty straight-forward too. We take a variable of type Ints<S...>, and a function, and apply the function with S....



    template<int... S, class Func>
    auto operator|(Ints<S...>, Func&& f)
    return f(S...);



    Proposed interface [Static case / ints usable as template parameters]



    As stated before, the static case has a similar interface to the dynamic case, and it won't be too much of a stretch conceptually. From a user standpoint, the only difference is that instead of using S... as the parameter pack, well useS.value...` as the pack.



    For each value, we want to encapsulate it in a corresponding type templated on the value. This allows us to access it in a constexpr context.



    template<int Value>
    struct ConstInt
    constexpr static int value = Value;
    ;


    To differentiate it from the dynamic case, I'm going to overload / instead of |. Otherwise, they behave similarly. The implementation is pretty much the same as the dynamic case, except that the values are wrapped in the ConstInt class, and each will have it's own type.



    template<int... S, class F>
    auto operator/(Ints<S...>, F&& func)
    return func(ConstInt<S>()...);



    Using this interface statically



    C++ allows us to access static members of a class using the same syntax as non-static members, without losing constexpr status.



    Let's say I have some ConstInt with a value of 10. I can directly use I.value as a template parameter, or I can use decltype(I)::value:



    // This is what'll be passed in as a parameter
    ConstInt<10> I;

    std::array<int, I.value> arr1;
    std::array<int, decltype(I)::value> arr2;
    // Both have length 10


    Expanding a parameter pack is therefore extraordinarily straight-forward, and it ends up being almost identical to the dynamic case, the only difference being the .value appended to S. Shown below are the examples from the dynamic case, this time using the static case syntax:



    Ints<1, 2, 3> ints;

    // Get a vector from ints
    auto vec = ints | [](auto... S) return std::vector S.value...; ;

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = ints | [](auto... S) return std::array S.value...; ;

    // Get a tuple from ints
    auto tup = ints | [](auto... S) return std::make_tuple(S.value...); ;

    // Get sum of ints using a fold expression
    auto sum = ints | [](auto... S) return (S.value + ...); ;


    So what's new? Because value is constexpr, S.value can be used trivially as a template parameter. In this example, we use S.value to index into a tuple using std::get:



    auto tupA = std::make_tuple(10.0, "Hello", 3); 

    auto indicies = Ints<2, 0, 1>;

    // tupB = 3, 10.0, "Hello"
    auto tupB = indicies / [&](auto... S)
    return std::make_tuple(std::get<S.value>(tupA)...);
    ;


    And in this example, we square every element in a sequence, and return a new sequence:



    auto ints = Ints<0, 1, 2, 3, 4, 5>(); 

    // ints_squared = Ints<0, 1, 4, 9, 16, 25>();
    auto ints_squared = ints / [](auto... S)
    return Ints<(S.value * S.value)...>();
    ;


    Alternative solution that avoids operator overloading



    If you want to avoid operator overloading, we can take some inspiration from functional programming and handle things with an unpack function, written like so:



    template<int... vals>
    auto unpack(Ints<vals...>)
    return [](auto&& f) return f(vals...); ;


    // Static case
    template<int... vals>
    auto unpack_static(Ints<vals...>)
    return [](auto&& f) return f(ConstInt<vals>()...); ;



    So what is unpack? This function takes a bunch of values, and it returns a function which takes another function and applies the function with the vals as inputs.



    The unpack function allows us to apply those values to a different function, as parameters.



    We can assign the result to a variable called apply_ints, and then we can use apply_ints to handle all the specific use-cases:



    Ints<1, 2, 3> ints; //this variable has our ints

    auto apply_ints = unpack(ints); // We use this function to unpack them


    We can re-write the examples from before, this time using apply_ints:



    // Get a vector from ints
    // vec = 1, 2, 3
    auto vec = apply_ints([](auto... S) return std::vector S...; );

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = apply_ints([](auto... S) return std::array S...; );

    // Get a tuple from ints
    // tup = 1, 2, 3
    auto tup = apply_ints([](auto... S) return std::make_tuple(S...); );

    // Get sum of ints using a fold expression
    auto sum = apply_ints([](auto... S) return (S + ...); );


    Appendix



    This appendix gives a brief overview showing how to use this syntax more generally (such as when working with multiple separate parameter packs).



    Bonus example: pairing up values from two separate packs



    To give you a better idea of the flexibility of this interface, here's an example where we use it to pair up values from two separate packs.



    Ints<1, 2, 3> intsA;
    Ints<10, 20, 30> intsB;

    // pairs = 1, 10, 2, 20, 3, 30
    auto pairs = intsA | [&](auto... S1) [&](auto... S2)
    return std::vector std::pairS1, S2... ;
    ;
    ;


    NB: MSVC and GCC both compile this example without issues, however clang chokes up on it. I assume MSVC and GCC are correct, but I don't know for sure.



    Bonus example: Getting a 2-dimensional times table



    This example is a little more complicated, but we can also create 2-dimensional arrays of values that draw from all combinations of values from separate packs.



    In this case, I use it to create a times table.



    Ints<1, 2, 3, 4, 5, 6, 7, 8, 9> digits;

    auto multiply = [](auto mul, auto... vals)
    return std::vector(mul * vals)...;
    ;

    auto times_table = digits | [&](auto... S1) [&](auto... S2)
    return std::vector multiply(S1, S2...)... ;
    ;
    ;





    share|improve this answer

























    • This would have been a really great answer in some other context - but the OP is specificly trying to avoid auxilery functions... so it's simply too complicated a solution for what is needed.

      – darune
      May 2 at 7:46






    • 1





      @darune: there is only one aux function, which is generic enough to be not a problem (i.e., there is no need to have one additional aux function for each use)

      – geza
      May 2 at 7:49






    • 1





      This really can be made into an immediately invoked lambda expression if OP wants to use it only in one place.

      – YSC
      May 2 at 7:50











    • IMO it's still shooting (way) above the target. you have just created a generalized function instead - and requires now a more convoluted way to create+apply the lambda function. While this can be great, IMO it is shooting above the target and not what OP is asking for !

      – darune
      May 2 at 8:02












    • I added an alternative solution that doesn't involve the creation of an apply_ints helper function, and looks more elegant

      – J. Antonio Perez
      May 2 at 8:11















    7














    What would the ideal interface look like?



    If given a variable of type Ints<S...>, we'd ideally be able to use S... with as little modification as possible.



    In this case, we can design an interface which allows us to use the parameter pack as an input to a variadic function or lambda, even going so far as to reuse the values as template parameters.



    Proposed interface [Dynamic case / ints passed as values]



    Both the static case and the dynamic case have similar interfaces, however the dynamic case is slightly cleaner, and makes for a better introduction. Given the variable and a function, we apply the function with the parameter pack contained in the definition of the variable.



    Ints<1, 2, 3> ints;

    // Get a vector from ints
    // vec = 1, 2, 3
    auto vec = ints | [](auto... S) return std::vector S...; ;

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = ints | [](auto... S) return std::array S...; ;

    // Get a tuple from ints
    // tup = 1, 2, 3
    auto tup = ints | [](auto... S) return std::make_tuple(S...); ;

    // Get sum of ints using a fold expression
    auto sum = ints | [](auto... S) return (S + ...); ;


    It's a simple, unified syntax which allows us to take S and use it as a parameter pack.



    Writing this interface



    This part is pretty straight-forward too. We take a variable of type Ints<S...>, and a function, and apply the function with S....



    template<int... S, class Func>
    auto operator|(Ints<S...>, Func&& f)
    return f(S...);



    Proposed interface [Static case / ints usable as template parameters]



    As stated before, the static case has a similar interface to the dynamic case, and it won't be too much of a stretch conceptually. From a user standpoint, the only difference is that instead of using S... as the parameter pack, well useS.value...` as the pack.



    For each value, we want to encapsulate it in a corresponding type templated on the value. This allows us to access it in a constexpr context.



    template<int Value>
    struct ConstInt
    constexpr static int value = Value;
    ;


    To differentiate it from the dynamic case, I'm going to overload / instead of |. Otherwise, they behave similarly. The implementation is pretty much the same as the dynamic case, except that the values are wrapped in the ConstInt class, and each will have it's own type.



    template<int... S, class F>
    auto operator/(Ints<S...>, F&& func)
    return func(ConstInt<S>()...);



    Using this interface statically



    C++ allows us to access static members of a class using the same syntax as non-static members, without losing constexpr status.



    Let's say I have some ConstInt with a value of 10. I can directly use I.value as a template parameter, or I can use decltype(I)::value:



    // This is what'll be passed in as a parameter
    ConstInt<10> I;

    std::array<int, I.value> arr1;
    std::array<int, decltype(I)::value> arr2;
    // Both have length 10


    Expanding a parameter pack is therefore extraordinarily straight-forward, and it ends up being almost identical to the dynamic case, the only difference being the .value appended to S. Shown below are the examples from the dynamic case, this time using the static case syntax:



    Ints<1, 2, 3> ints;

    // Get a vector from ints
    auto vec = ints | [](auto... S) return std::vector S.value...; ;

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = ints | [](auto... S) return std::array S.value...; ;

    // Get a tuple from ints
    auto tup = ints | [](auto... S) return std::make_tuple(S.value...); ;

    // Get sum of ints using a fold expression
    auto sum = ints | [](auto... S) return (S.value + ...); ;


    So what's new? Because value is constexpr, S.value can be used trivially as a template parameter. In this example, we use S.value to index into a tuple using std::get:



    auto tupA = std::make_tuple(10.0, "Hello", 3); 

    auto indicies = Ints<2, 0, 1>;

    // tupB = 3, 10.0, "Hello"
    auto tupB = indicies / [&](auto... S)
    return std::make_tuple(std::get<S.value>(tupA)...);
    ;


    And in this example, we square every element in a sequence, and return a new sequence:



    auto ints = Ints<0, 1, 2, 3, 4, 5>(); 

    // ints_squared = Ints<0, 1, 4, 9, 16, 25>();
    auto ints_squared = ints / [](auto... S)
    return Ints<(S.value * S.value)...>();
    ;


    Alternative solution that avoids operator overloading



    If you want to avoid operator overloading, we can take some inspiration from functional programming and handle things with an unpack function, written like so:



    template<int... vals>
    auto unpack(Ints<vals...>)
    return [](auto&& f) return f(vals...); ;


    // Static case
    template<int... vals>
    auto unpack_static(Ints<vals...>)
    return [](auto&& f) return f(ConstInt<vals>()...); ;



    So what is unpack? This function takes a bunch of values, and it returns a function which takes another function and applies the function with the vals as inputs.



    The unpack function allows us to apply those values to a different function, as parameters.



    We can assign the result to a variable called apply_ints, and then we can use apply_ints to handle all the specific use-cases:



    Ints<1, 2, 3> ints; //this variable has our ints

    auto apply_ints = unpack(ints); // We use this function to unpack them


    We can re-write the examples from before, this time using apply_ints:



    // Get a vector from ints
    // vec = 1, 2, 3
    auto vec = apply_ints([](auto... S) return std::vector S...; );

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = apply_ints([](auto... S) return std::array S...; );

    // Get a tuple from ints
    // tup = 1, 2, 3
    auto tup = apply_ints([](auto... S) return std::make_tuple(S...); );

    // Get sum of ints using a fold expression
    auto sum = apply_ints([](auto... S) return (S + ...); );


    Appendix



    This appendix gives a brief overview showing how to use this syntax more generally (such as when working with multiple separate parameter packs).



    Bonus example: pairing up values from two separate packs



    To give you a better idea of the flexibility of this interface, here's an example where we use it to pair up values from two separate packs.



    Ints<1, 2, 3> intsA;
    Ints<10, 20, 30> intsB;

    // pairs = 1, 10, 2, 20, 3, 30
    auto pairs = intsA | [&](auto... S1) [&](auto... S2)
    return std::vector std::pairS1, S2... ;
    ;
    ;


    NB: MSVC and GCC both compile this example without issues, however clang chokes up on it. I assume MSVC and GCC are correct, but I don't know for sure.



    Bonus example: Getting a 2-dimensional times table



    This example is a little more complicated, but we can also create 2-dimensional arrays of values that draw from all combinations of values from separate packs.



    In this case, I use it to create a times table.



    Ints<1, 2, 3, 4, 5, 6, 7, 8, 9> digits;

    auto multiply = [](auto mul, auto... vals)
    return std::vector(mul * vals)...;
    ;

    auto times_table = digits | [&](auto... S1) [&](auto... S2)
    return std::vector multiply(S1, S2...)... ;
    ;
    ;





    share|improve this answer

























    • This would have been a really great answer in some other context - but the OP is specificly trying to avoid auxilery functions... so it's simply too complicated a solution for what is needed.

      – darune
      May 2 at 7:46






    • 1





      @darune: there is only one aux function, which is generic enough to be not a problem (i.e., there is no need to have one additional aux function for each use)

      – geza
      May 2 at 7:49






    • 1





      This really can be made into an immediately invoked lambda expression if OP wants to use it only in one place.

      – YSC
      May 2 at 7:50











    • IMO it's still shooting (way) above the target. you have just created a generalized function instead - and requires now a more convoluted way to create+apply the lambda function. While this can be great, IMO it is shooting above the target and not what OP is asking for !

      – darune
      May 2 at 8:02












    • I added an alternative solution that doesn't involve the creation of an apply_ints helper function, and looks more elegant

      – J. Antonio Perez
      May 2 at 8:11













    7












    7








    7







    What would the ideal interface look like?



    If given a variable of type Ints<S...>, we'd ideally be able to use S... with as little modification as possible.



    In this case, we can design an interface which allows us to use the parameter pack as an input to a variadic function or lambda, even going so far as to reuse the values as template parameters.



    Proposed interface [Dynamic case / ints passed as values]



    Both the static case and the dynamic case have similar interfaces, however the dynamic case is slightly cleaner, and makes for a better introduction. Given the variable and a function, we apply the function with the parameter pack contained in the definition of the variable.



    Ints<1, 2, 3> ints;

    // Get a vector from ints
    // vec = 1, 2, 3
    auto vec = ints | [](auto... S) return std::vector S...; ;

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = ints | [](auto... S) return std::array S...; ;

    // Get a tuple from ints
    // tup = 1, 2, 3
    auto tup = ints | [](auto... S) return std::make_tuple(S...); ;

    // Get sum of ints using a fold expression
    auto sum = ints | [](auto... S) return (S + ...); ;


    It's a simple, unified syntax which allows us to take S and use it as a parameter pack.



    Writing this interface



    This part is pretty straight-forward too. We take a variable of type Ints<S...>, and a function, and apply the function with S....



    template<int... S, class Func>
    auto operator|(Ints<S...>, Func&& f)
    return f(S...);



    Proposed interface [Static case / ints usable as template parameters]



    As stated before, the static case has a similar interface to the dynamic case, and it won't be too much of a stretch conceptually. From a user standpoint, the only difference is that instead of using S... as the parameter pack, well useS.value...` as the pack.



    For each value, we want to encapsulate it in a corresponding type templated on the value. This allows us to access it in a constexpr context.



    template<int Value>
    struct ConstInt
    constexpr static int value = Value;
    ;


    To differentiate it from the dynamic case, I'm going to overload / instead of |. Otherwise, they behave similarly. The implementation is pretty much the same as the dynamic case, except that the values are wrapped in the ConstInt class, and each will have it's own type.



    template<int... S, class F>
    auto operator/(Ints<S...>, F&& func)
    return func(ConstInt<S>()...);



    Using this interface statically



    C++ allows us to access static members of a class using the same syntax as non-static members, without losing constexpr status.



    Let's say I have some ConstInt with a value of 10. I can directly use I.value as a template parameter, or I can use decltype(I)::value:



    // This is what'll be passed in as a parameter
    ConstInt<10> I;

    std::array<int, I.value> arr1;
    std::array<int, decltype(I)::value> arr2;
    // Both have length 10


    Expanding a parameter pack is therefore extraordinarily straight-forward, and it ends up being almost identical to the dynamic case, the only difference being the .value appended to S. Shown below are the examples from the dynamic case, this time using the static case syntax:



    Ints<1, 2, 3> ints;

    // Get a vector from ints
    auto vec = ints | [](auto... S) return std::vector S.value...; ;

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = ints | [](auto... S) return std::array S.value...; ;

    // Get a tuple from ints
    auto tup = ints | [](auto... S) return std::make_tuple(S.value...); ;

    // Get sum of ints using a fold expression
    auto sum = ints | [](auto... S) return (S.value + ...); ;


    So what's new? Because value is constexpr, S.value can be used trivially as a template parameter. In this example, we use S.value to index into a tuple using std::get:



    auto tupA = std::make_tuple(10.0, "Hello", 3); 

    auto indicies = Ints<2, 0, 1>;

    // tupB = 3, 10.0, "Hello"
    auto tupB = indicies / [&](auto... S)
    return std::make_tuple(std::get<S.value>(tupA)...);
    ;


    And in this example, we square every element in a sequence, and return a new sequence:



    auto ints = Ints<0, 1, 2, 3, 4, 5>(); 

    // ints_squared = Ints<0, 1, 4, 9, 16, 25>();
    auto ints_squared = ints / [](auto... S)
    return Ints<(S.value * S.value)...>();
    ;


    Alternative solution that avoids operator overloading



    If you want to avoid operator overloading, we can take some inspiration from functional programming and handle things with an unpack function, written like so:



    template<int... vals>
    auto unpack(Ints<vals...>)
    return [](auto&& f) return f(vals...); ;


    // Static case
    template<int... vals>
    auto unpack_static(Ints<vals...>)
    return [](auto&& f) return f(ConstInt<vals>()...); ;



    So what is unpack? This function takes a bunch of values, and it returns a function which takes another function and applies the function with the vals as inputs.



    The unpack function allows us to apply those values to a different function, as parameters.



    We can assign the result to a variable called apply_ints, and then we can use apply_ints to handle all the specific use-cases:



    Ints<1, 2, 3> ints; //this variable has our ints

    auto apply_ints = unpack(ints); // We use this function to unpack them


    We can re-write the examples from before, this time using apply_ints:



    // Get a vector from ints
    // vec = 1, 2, 3
    auto vec = apply_ints([](auto... S) return std::vector S...; );

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = apply_ints([](auto... S) return std::array S...; );

    // Get a tuple from ints
    // tup = 1, 2, 3
    auto tup = apply_ints([](auto... S) return std::make_tuple(S...); );

    // Get sum of ints using a fold expression
    auto sum = apply_ints([](auto... S) return (S + ...); );


    Appendix



    This appendix gives a brief overview showing how to use this syntax more generally (such as when working with multiple separate parameter packs).



    Bonus example: pairing up values from two separate packs



    To give you a better idea of the flexibility of this interface, here's an example where we use it to pair up values from two separate packs.



    Ints<1, 2, 3> intsA;
    Ints<10, 20, 30> intsB;

    // pairs = 1, 10, 2, 20, 3, 30
    auto pairs = intsA | [&](auto... S1) [&](auto... S2)
    return std::vector std::pairS1, S2... ;
    ;
    ;


    NB: MSVC and GCC both compile this example without issues, however clang chokes up on it. I assume MSVC and GCC are correct, but I don't know for sure.



    Bonus example: Getting a 2-dimensional times table



    This example is a little more complicated, but we can also create 2-dimensional arrays of values that draw from all combinations of values from separate packs.



    In this case, I use it to create a times table.



    Ints<1, 2, 3, 4, 5, 6, 7, 8, 9> digits;

    auto multiply = [](auto mul, auto... vals)
    return std::vector(mul * vals)...;
    ;

    auto times_table = digits | [&](auto... S1) [&](auto... S2)
    return std::vector multiply(S1, S2...)... ;
    ;
    ;





    share|improve this answer















    What would the ideal interface look like?



    If given a variable of type Ints<S...>, we'd ideally be able to use S... with as little modification as possible.



    In this case, we can design an interface which allows us to use the parameter pack as an input to a variadic function or lambda, even going so far as to reuse the values as template parameters.



    Proposed interface [Dynamic case / ints passed as values]



    Both the static case and the dynamic case have similar interfaces, however the dynamic case is slightly cleaner, and makes for a better introduction. Given the variable and a function, we apply the function with the parameter pack contained in the definition of the variable.



    Ints<1, 2, 3> ints;

    // Get a vector from ints
    // vec = 1, 2, 3
    auto vec = ints | [](auto... S) return std::vector S...; ;

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = ints | [](auto... S) return std::array S...; ;

    // Get a tuple from ints
    // tup = 1, 2, 3
    auto tup = ints | [](auto... S) return std::make_tuple(S...); ;

    // Get sum of ints using a fold expression
    auto sum = ints | [](auto... S) return (S + ...); ;


    It's a simple, unified syntax which allows us to take S and use it as a parameter pack.



    Writing this interface



    This part is pretty straight-forward too. We take a variable of type Ints<S...>, and a function, and apply the function with S....



    template<int... S, class Func>
    auto operator|(Ints<S...>, Func&& f)
    return f(S...);



    Proposed interface [Static case / ints usable as template parameters]



    As stated before, the static case has a similar interface to the dynamic case, and it won't be too much of a stretch conceptually. From a user standpoint, the only difference is that instead of using S... as the parameter pack, well useS.value...` as the pack.



    For each value, we want to encapsulate it in a corresponding type templated on the value. This allows us to access it in a constexpr context.



    template<int Value>
    struct ConstInt
    constexpr static int value = Value;
    ;


    To differentiate it from the dynamic case, I'm going to overload / instead of |. Otherwise, they behave similarly. The implementation is pretty much the same as the dynamic case, except that the values are wrapped in the ConstInt class, and each will have it's own type.



    template<int... S, class F>
    auto operator/(Ints<S...>, F&& func)
    return func(ConstInt<S>()...);



    Using this interface statically



    C++ allows us to access static members of a class using the same syntax as non-static members, without losing constexpr status.



    Let's say I have some ConstInt with a value of 10. I can directly use I.value as a template parameter, or I can use decltype(I)::value:



    // This is what'll be passed in as a parameter
    ConstInt<10> I;

    std::array<int, I.value> arr1;
    std::array<int, decltype(I)::value> arr2;
    // Both have length 10


    Expanding a parameter pack is therefore extraordinarily straight-forward, and it ends up being almost identical to the dynamic case, the only difference being the .value appended to S. Shown below are the examples from the dynamic case, this time using the static case syntax:



    Ints<1, 2, 3> ints;

    // Get a vector from ints
    auto vec = ints | [](auto... S) return std::vector S.value...; ;

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = ints | [](auto... S) return std::array S.value...; ;

    // Get a tuple from ints
    auto tup = ints | [](auto... S) return std::make_tuple(S.value...); ;

    // Get sum of ints using a fold expression
    auto sum = ints | [](auto... S) return (S.value + ...); ;


    So what's new? Because value is constexpr, S.value can be used trivially as a template parameter. In this example, we use S.value to index into a tuple using std::get:



    auto tupA = std::make_tuple(10.0, "Hello", 3); 

    auto indicies = Ints<2, 0, 1>;

    // tupB = 3, 10.0, "Hello"
    auto tupB = indicies / [&](auto... S)
    return std::make_tuple(std::get<S.value>(tupA)...);
    ;


    And in this example, we square every element in a sequence, and return a new sequence:



    auto ints = Ints<0, 1, 2, 3, 4, 5>(); 

    // ints_squared = Ints<0, 1, 4, 9, 16, 25>();
    auto ints_squared = ints / [](auto... S)
    return Ints<(S.value * S.value)...>();
    ;


    Alternative solution that avoids operator overloading



    If you want to avoid operator overloading, we can take some inspiration from functional programming and handle things with an unpack function, written like so:



    template<int... vals>
    auto unpack(Ints<vals...>)
    return [](auto&& f) return f(vals...); ;


    // Static case
    template<int... vals>
    auto unpack_static(Ints<vals...>)
    return [](auto&& f) return f(ConstInt<vals>()...); ;



    So what is unpack? This function takes a bunch of values, and it returns a function which takes another function and applies the function with the vals as inputs.



    The unpack function allows us to apply those values to a different function, as parameters.



    We can assign the result to a variable called apply_ints, and then we can use apply_ints to handle all the specific use-cases:



    Ints<1, 2, 3> ints; //this variable has our ints

    auto apply_ints = unpack(ints); // We use this function to unpack them


    We can re-write the examples from before, this time using apply_ints:



    // Get a vector from ints
    // vec = 1, 2, 3
    auto vec = apply_ints([](auto... S) return std::vector S...; );

    // Get an array from ints
    // arr = 1, 2, 3
    auto arr = apply_ints([](auto... S) return std::array S...; );

    // Get a tuple from ints
    // tup = 1, 2, 3
    auto tup = apply_ints([](auto... S) return std::make_tuple(S...); );

    // Get sum of ints using a fold expression
    auto sum = apply_ints([](auto... S) return (S + ...); );


    Appendix



    This appendix gives a brief overview showing how to use this syntax more generally (such as when working with multiple separate parameter packs).



    Bonus example: pairing up values from two separate packs



    To give you a better idea of the flexibility of this interface, here's an example where we use it to pair up values from two separate packs.



    Ints<1, 2, 3> intsA;
    Ints<10, 20, 30> intsB;

    // pairs = 1, 10, 2, 20, 3, 30
    auto pairs = intsA | [&](auto... S1) [&](auto... S2)
    return std::vector std::pairS1, S2... ;
    ;
    ;


    NB: MSVC and GCC both compile this example without issues, however clang chokes up on it. I assume MSVC and GCC are correct, but I don't know for sure.



    Bonus example: Getting a 2-dimensional times table



    This example is a little more complicated, but we can also create 2-dimensional arrays of values that draw from all combinations of values from separate packs.



    In this case, I use it to create a times table.



    Ints<1, 2, 3, 4, 5, 6, 7, 8, 9> digits;

    auto multiply = [](auto mul, auto... vals)
    return std::vector(mul * vals)...;
    ;

    auto times_table = digits | [&](auto... S1) [&](auto... S2)
    return std::vector multiply(S1, S2...)... ;
    ;
    ;






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited May 2 at 21:35

























    answered May 2 at 7:41









    J. Antonio PerezJ. Antonio Perez

    4,291926




    4,291926












    • This would have been a really great answer in some other context - but the OP is specificly trying to avoid auxilery functions... so it's simply too complicated a solution for what is needed.

      – darune
      May 2 at 7:46






    • 1





      @darune: there is only one aux function, which is generic enough to be not a problem (i.e., there is no need to have one additional aux function for each use)

      – geza
      May 2 at 7:49






    • 1





      This really can be made into an immediately invoked lambda expression if OP wants to use it only in one place.

      – YSC
      May 2 at 7:50











    • IMO it's still shooting (way) above the target. you have just created a generalized function instead - and requires now a more convoluted way to create+apply the lambda function. While this can be great, IMO it is shooting above the target and not what OP is asking for !

      – darune
      May 2 at 8:02












    • I added an alternative solution that doesn't involve the creation of an apply_ints helper function, and looks more elegant

      – J. Antonio Perez
      May 2 at 8:11

















    • This would have been a really great answer in some other context - but the OP is specificly trying to avoid auxilery functions... so it's simply too complicated a solution for what is needed.

      – darune
      May 2 at 7:46






    • 1





      @darune: there is only one aux function, which is generic enough to be not a problem (i.e., there is no need to have one additional aux function for each use)

      – geza
      May 2 at 7:49






    • 1





      This really can be made into an immediately invoked lambda expression if OP wants to use it only in one place.

      – YSC
      May 2 at 7:50











    • IMO it's still shooting (way) above the target. you have just created a generalized function instead - and requires now a more convoluted way to create+apply the lambda function. While this can be great, IMO it is shooting above the target and not what OP is asking for !

      – darune
      May 2 at 8:02












    • I added an alternative solution that doesn't involve the creation of an apply_ints helper function, and looks more elegant

      – J. Antonio Perez
      May 2 at 8:11
















    This would have been a really great answer in some other context - but the OP is specificly trying to avoid auxilery functions... so it's simply too complicated a solution for what is needed.

    – darune
    May 2 at 7:46





    This would have been a really great answer in some other context - but the OP is specificly trying to avoid auxilery functions... so it's simply too complicated a solution for what is needed.

    – darune
    May 2 at 7:46




    1




    1





    @darune: there is only one aux function, which is generic enough to be not a problem (i.e., there is no need to have one additional aux function for each use)

    – geza
    May 2 at 7:49





    @darune: there is only one aux function, which is generic enough to be not a problem (i.e., there is no need to have one additional aux function for each use)

    – geza
    May 2 at 7:49




    1




    1





    This really can be made into an immediately invoked lambda expression if OP wants to use it only in one place.

    – YSC
    May 2 at 7:50





    This really can be made into an immediately invoked lambda expression if OP wants to use it only in one place.

    – YSC
    May 2 at 7:50













    IMO it's still shooting (way) above the target. you have just created a generalized function instead - and requires now a more convoluted way to create+apply the lambda function. While this can be great, IMO it is shooting above the target and not what OP is asking for !

    – darune
    May 2 at 8:02






    IMO it's still shooting (way) above the target. you have just created a generalized function instead - and requires now a more convoluted way to create+apply the lambda function. While this can be great, IMO it is shooting above the target and not what OP is asking for !

    – darune
    May 2 at 8:02














    I added an alternative solution that doesn't involve the creation of an apply_ints helper function, and looks more elegant

    – J. Antonio Perez
    May 2 at 8:11





    I added an alternative solution that doesn't involve the creation of an apply_ints helper function, and looks more elegant

    – J. Antonio Perez
    May 2 at 8:11













    6














    In C++2a, you might use templated lambda to define your helper inside your function, something like:



    auto v = []<std::size_t...Is>(std::index_sequence<Is...>)return std::vectorIs...;(seq);
    // ^^^^^^^^^^^^^^^^^^ New in C++2a


    Demo






    share|improve this answer























    • Thanks. This seems to be very simple way of doing inside-function pattern matching

      – i.stav
      May 2 at 8:40












    • It mostly equivalent to functor with template <std::size_t...Is> auto operator()(std::index_sequence<Is...>) const;.

      – Jarod42
      May 2 at 8:44















    6














    In C++2a, you might use templated lambda to define your helper inside your function, something like:



    auto v = []<std::size_t...Is>(std::index_sequence<Is...>)return std::vectorIs...;(seq);
    // ^^^^^^^^^^^^^^^^^^ New in C++2a


    Demo






    share|improve this answer























    • Thanks. This seems to be very simple way of doing inside-function pattern matching

      – i.stav
      May 2 at 8:40












    • It mostly equivalent to functor with template <std::size_t...Is> auto operator()(std::index_sequence<Is...>) const;.

      – Jarod42
      May 2 at 8:44













    6












    6








    6







    In C++2a, you might use templated lambda to define your helper inside your function, something like:



    auto v = []<std::size_t...Is>(std::index_sequence<Is...>)return std::vectorIs...;(seq);
    // ^^^^^^^^^^^^^^^^^^ New in C++2a


    Demo






    share|improve this answer













    In C++2a, you might use templated lambda to define your helper inside your function, something like:



    auto v = []<std::size_t...Is>(std::index_sequence<Is...>)return std::vectorIs...;(seq);
    // ^^^^^^^^^^^^^^^^^^ New in C++2a


    Demo







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered May 2 at 8:34









    Jarod42Jarod42

    121k12107191




    121k12107191












    • Thanks. This seems to be very simple way of doing inside-function pattern matching

      – i.stav
      May 2 at 8:40












    • It mostly equivalent to functor with template <std::size_t...Is> auto operator()(std::index_sequence<Is...>) const;.

      – Jarod42
      May 2 at 8:44

















    • Thanks. This seems to be very simple way of doing inside-function pattern matching

      – i.stav
      May 2 at 8:40












    • It mostly equivalent to functor with template <std::size_t...Is> auto operator()(std::index_sequence<Is...>) const;.

      – Jarod42
      May 2 at 8:44
















    Thanks. This seems to be very simple way of doing inside-function pattern matching

    – i.stav
    May 2 at 8:40






    Thanks. This seems to be very simple way of doing inside-function pattern matching

    – i.stav
    May 2 at 8:40














    It mostly equivalent to functor with template <std::size_t...Is> auto operator()(std::index_sequence<Is...>) const;.

    – Jarod42
    May 2 at 8:44





    It mostly equivalent to functor with template <std::size_t...Is> auto operator()(std::index_sequence<Is...>) const;.

    – Jarod42
    May 2 at 8:44











    1














    I would suggest adding functions to the struct Int to get different representations



    #include <vector>
    #include <array>

    template<int ...values>
    struct Ints
    auto getAsVector() const
    return std::vector<int>( values... );


    constexpr auto getAsArray() const
    return std::array<int, sizeof...(values)>( values... );

    ;

    class MyClass

    public:
    Ints<1, 2, 3> get() return Ints<1, 2, 3>();
    ;

    int main()
    MyClass a;
    auto array = a.get().getAsVector();
    return array.size();







    share|improve this answer


















    • 1





      Nope. Making into vector is just for explain. Ints and MyFunc is toy example. I don't even want to do that. I'm asking general solution

      – i.stav
      May 2 at 7:09












    • @i.stav There is no truly general solution. You have to use helper functions/classes, but you can try to make those helpers as general as possible (e.g. you could pass container as template <typename> typename> template parameter to them).

      – HolyBlackCat
      May 2 at 7:21












    • @HolyBlackCat Ok thanks, but what I really wonder is like this : why doesn't c++ provide simple and clear way like MyFunc2? Why isn't pattern matching available inside the function?

      – i.stav
      May 2 at 7:26















    1














    I would suggest adding functions to the struct Int to get different representations



    #include <vector>
    #include <array>

    template<int ...values>
    struct Ints
    auto getAsVector() const
    return std::vector<int>( values... );


    constexpr auto getAsArray() const
    return std::array<int, sizeof...(values)>( values... );

    ;

    class MyClass

    public:
    Ints<1, 2, 3> get() return Ints<1, 2, 3>();
    ;

    int main()
    MyClass a;
    auto array = a.get().getAsVector();
    return array.size();







    share|improve this answer


















    • 1





      Nope. Making into vector is just for explain. Ints and MyFunc is toy example. I don't even want to do that. I'm asking general solution

      – i.stav
      May 2 at 7:09












    • @i.stav There is no truly general solution. You have to use helper functions/classes, but you can try to make those helpers as general as possible (e.g. you could pass container as template <typename> typename> template parameter to them).

      – HolyBlackCat
      May 2 at 7:21












    • @HolyBlackCat Ok thanks, but what I really wonder is like this : why doesn't c++ provide simple and clear way like MyFunc2? Why isn't pattern matching available inside the function?

      – i.stav
      May 2 at 7:26













    1












    1








    1







    I would suggest adding functions to the struct Int to get different representations



    #include <vector>
    #include <array>

    template<int ...values>
    struct Ints
    auto getAsVector() const
    return std::vector<int>( values... );


    constexpr auto getAsArray() const
    return std::array<int, sizeof...(values)>( values... );

    ;

    class MyClass

    public:
    Ints<1, 2, 3> get() return Ints<1, 2, 3>();
    ;

    int main()
    MyClass a;
    auto array = a.get().getAsVector();
    return array.size();







    share|improve this answer













    I would suggest adding functions to the struct Int to get different representations



    #include <vector>
    #include <array>

    template<int ...values>
    struct Ints
    auto getAsVector() const
    return std::vector<int>( values... );


    constexpr auto getAsArray() const
    return std::array<int, sizeof...(values)>( values... );

    ;

    class MyClass

    public:
    Ints<1, 2, 3> get() return Ints<1, 2, 3>();
    ;

    int main()
    MyClass a;
    auto array = a.get().getAsVector();
    return array.size();








    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered May 2 at 7:01









    Nishant SinghNishant Singh

    1,5091014




    1,5091014







    • 1





      Nope. Making into vector is just for explain. Ints and MyFunc is toy example. I don't even want to do that. I'm asking general solution

      – i.stav
      May 2 at 7:09












    • @i.stav There is no truly general solution. You have to use helper functions/classes, but you can try to make those helpers as general as possible (e.g. you could pass container as template <typename> typename> template parameter to them).

      – HolyBlackCat
      May 2 at 7:21












    • @HolyBlackCat Ok thanks, but what I really wonder is like this : why doesn't c++ provide simple and clear way like MyFunc2? Why isn't pattern matching available inside the function?

      – i.stav
      May 2 at 7:26












    • 1





      Nope. Making into vector is just for explain. Ints and MyFunc is toy example. I don't even want to do that. I'm asking general solution

      – i.stav
      May 2 at 7:09












    • @i.stav There is no truly general solution. You have to use helper functions/classes, but you can try to make those helpers as general as possible (e.g. you could pass container as template <typename> typename> template parameter to them).

      – HolyBlackCat
      May 2 at 7:21












    • @HolyBlackCat Ok thanks, but what I really wonder is like this : why doesn't c++ provide simple and clear way like MyFunc2? Why isn't pattern matching available inside the function?

      – i.stav
      May 2 at 7:26







    1




    1





    Nope. Making into vector is just for explain. Ints and MyFunc is toy example. I don't even want to do that. I'm asking general solution

    – i.stav
    May 2 at 7:09






    Nope. Making into vector is just for explain. Ints and MyFunc is toy example. I don't even want to do that. I'm asking general solution

    – i.stav
    May 2 at 7:09














    @i.stav There is no truly general solution. You have to use helper functions/classes, but you can try to make those helpers as general as possible (e.g. you could pass container as template <typename> typename> template parameter to them).

    – HolyBlackCat
    May 2 at 7:21






    @i.stav There is no truly general solution. You have to use helper functions/classes, but you can try to make those helpers as general as possible (e.g. you could pass container as template <typename> typename> template parameter to them).

    – HolyBlackCat
    May 2 at 7:21














    @HolyBlackCat Ok thanks, but what I really wonder is like this : why doesn't c++ provide simple and clear way like MyFunc2? Why isn't pattern matching available inside the function?

    – i.stav
    May 2 at 7:26





    @HolyBlackCat Ok thanks, but what I really wonder is like this : why doesn't c++ provide simple and clear way like MyFunc2? Why isn't pattern matching available inside the function?

    – i.stav
    May 2 at 7:26











    1














    If you don't use/create a helper template, you need some other way to provide the values.



    The most simple, canonical and general way I can think of, is to put them in that same class scope, so that your Ints struct becomes:



    template<int ...ints>
    struct Ints
    constexpr static std::initializer_list<int> vals = ints...;
    ;


    Since it is constexpr it should be evaluated at compile time and not incur a runtime cost.
    Now you will be able do something like:



    return std::vector<int>(ints.vals);





    share|improve this answer





























      1














      If you don't use/create a helper template, you need some other way to provide the values.



      The most simple, canonical and general way I can think of, is to put them in that same class scope, so that your Ints struct becomes:



      template<int ...ints>
      struct Ints
      constexpr static std::initializer_list<int> vals = ints...;
      ;


      Since it is constexpr it should be evaluated at compile time and not incur a runtime cost.
      Now you will be able do something like:



      return std::vector<int>(ints.vals);





      share|improve this answer



























        1












        1








        1







        If you don't use/create a helper template, you need some other way to provide the values.



        The most simple, canonical and general way I can think of, is to put them in that same class scope, so that your Ints struct becomes:



        template<int ...ints>
        struct Ints
        constexpr static std::initializer_list<int> vals = ints...;
        ;


        Since it is constexpr it should be evaluated at compile time and not incur a runtime cost.
        Now you will be able do something like:



        return std::vector<int>(ints.vals);





        share|improve this answer















        If you don't use/create a helper template, you need some other way to provide the values.



        The most simple, canonical and general way I can think of, is to put them in that same class scope, so that your Ints struct becomes:



        template<int ...ints>
        struct Ints
        constexpr static std::initializer_list<int> vals = ints...;
        ;


        Since it is constexpr it should be evaluated at compile time and not incur a runtime cost.
        Now you will be able do something like:



        return std::vector<int>(ints.vals);






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited May 2 at 7:50

























        answered May 2 at 7:28









        darunedarune

        2,161823




        2,161823



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55946950%2fhow-to-retrieve-variadic-template-parameters-without-auxillary-function-template%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Club Baloncesto Breogán Índice Historia | Pavillón | Nome | O Breogán na cultura popular | Xogadores | Adestradores | Presidentes | Palmarés | Historial | Líderes | Notas | Véxase tamén | Menú de navegacióncbbreogan.galCadroGuía oficial da ACB 2009-10, páxina 201Guía oficial ACB 1992, páxina 183. Editorial DB.É de 6.500 espectadores sentados axeitándose á última normativa"Estudiantes Junior, entre as mellores canteiras"o orixinalHemeroteca El Mundo Deportivo, 16 setembro de 1970, páxina 12Historia do BreogánAlfredo Pérez, o último canoneiroHistoria C.B. BreogánHemeroteca de El Mundo DeportivoJimmy Wright, norteamericano do Breogán deixará Lugo por ameazas de morteResultados de Breogán en 1986-87Resultados de Breogán en 1990-91Ficha de Velimir Perasović en acb.comResultados de Breogán en 1994-95Breogán arrasa al Barça. "El Mundo Deportivo", 27 de setembro de 1999, páxina 58CB Breogán - FC BarcelonaA FEB invita a participar nunha nova Liga EuropeaCharlie Bell na prensa estatalMáximos anotadores 2005Tempada 2005-06 : Tódolos Xogadores da Xornada""Non quero pensar nunha man negra, mais pregúntome que está a pasar""o orixinalRaúl López, orgulloso dos xogadores, presume da boa saúde económica do BreogánJulio González confirma que cesa como presidente del BreogánHomenaxe a Lisardo GómezA tempada do rexurdimento celesteEntrevista a Lisardo GómezEl COB dinamita el Pazo para forzar el quinto (69-73)Cafés Candelas, patrocinador del CB Breogán"Suso Lázare, novo presidente do Breogán"o orixinalCafés Candelas Breogán firma el mayor triunfo de la historiaEl Breogán realizará 17 homenajes por su cincuenta aniversario"O Breogán honra ao seu fundador e primeiro presidente"o orixinalMiguel Giao recibiu a homenaxe do PazoHomenaxe aos primeiros gladiadores celestesO home que nos amosa como ver o Breo co corazónTita Franco será homenaxeada polos #50anosdeBreoJulio Vila recibirá unha homenaxe in memoriam polos #50anosdeBreo"O Breogán homenaxeará aos seus aboados máis veteráns"Pechada ovación a «Capi» Sanmartín e Ricardo «Corazón de González»Homenaxe por décadas de informaciónPaco García volve ao Pazo con motivo do 50 aniversario"Resultados y clasificaciones""O Cafés Candelas Breogán, campión da Copa Princesa""O Cafés Candelas Breogán, equipo ACB"C.B. Breogán"Proxecto social"o orixinal"Centros asociados"o orixinalFicha en imdb.comMario Camus trata la recuperación del amor en 'La vieja música', su última película"Páxina web oficial""Club Baloncesto Breogán""C. B. Breogán S.A.D."eehttp://www.fegaba.com

            Vilaño, A Laracha Índice Patrimonio | Lugares e parroquias | Véxase tamén | Menú de navegación43°14′52″N 8°36′03″O / 43.24775, -8.60070

            Cegueira Índice Epidemioloxía | Deficiencia visual | Tipos de cegueira | Principais causas de cegueira | Tratamento | Técnicas de adaptación e axudas | Vida dos cegos | Primeiros auxilios | Crenzas respecto das persoas cegas | Crenzas das persoas cegas | O neno deficiente visual | Aspectos psicolóxicos da cegueira | Notas | Véxase tamén | Menú de navegación54.054.154.436928256blindnessDicionario da Real Academia GalegaPortal das Palabras"International Standards: Visual Standards — Aspects and Ranges of Vision Loss with Emphasis on Population Surveys.""Visual impairment and blindness""Presentan un plan para previr a cegueira"o orixinalACCDV Associació Catalana de Cecs i Disminuïts Visuals - PMFTrachoma"Effect of gene therapy on visual function in Leber's congenital amaurosis"1844137110.1056/NEJMoa0802268Cans guía - os mellores amigos dos cegosArquivadoEscola de cans guía para cegos en Mortágua, PortugalArquivado"Tecnología para ciegos y deficientes visuales. Recopilación de recursos gratuitos en la Red""Colorino""‘COL.diesis’, escuchar los sonidos del color""COL.diesis: Transforming Colour into Melody and Implementing the Result in a Colour Sensor Device"o orixinal"Sistema de desarrollo de sinestesia color-sonido para invidentes utilizando un protocolo de audio""Enseñanza táctil - geometría y color. Juegos didácticos para niños ciegos y videntes""Sistema Constanz"L'ocupació laboral dels cecs a l'Estat espanyol està pràcticament equiparada a la de les persones amb visió, entrevista amb Pedro ZuritaONCE (Organización Nacional de Cegos de España)Prevención da cegueiraDescrición de deficiencias visuais (Disc@pnet)Braillín, un boneco atractivo para calquera neno, con ou sen discapacidade, que permite familiarizarse co sistema de escritura e lectura brailleAxudas Técnicas36838ID00897494007150-90057129528256DOID:1432HP:0000618D001766C10.597.751.941.162C97109C0155020