Is there a way to get a given number of inputs where the number is given by a template in compile time in...












6














For example, suppose I make a class like below:



template <unsigned int INPUT_SIZE>
class A{
public:
int operator()(int input, ...){ // get INPUT_SIZE-many inputs
// return sum;
}
};


I want to get input as many as INPUT_SIZE, not more or less. How can I achieve that?



Also, I am using c++11, but if there is a better way in c++14 or above, I would also like to know.










share|improve this question
























  • With a for loop.
    – tkausl
    3 hours ago










  • @tkausl Can you give an example of how that would look?
    – Lightness Races in Orbit
    3 hours ago






  • 1




    Does it need to be SFINAE-friendly? If not, I'd use a static_assert inside the body of operator(); if so, I'd go with Jans's answer until C++20, at which point I think you can put the sizeof... in a requires clause.
    – Daniel H
    2 hours ago


















6














For example, suppose I make a class like below:



template <unsigned int INPUT_SIZE>
class A{
public:
int operator()(int input, ...){ // get INPUT_SIZE-many inputs
// return sum;
}
};


I want to get input as many as INPUT_SIZE, not more or less. How can I achieve that?



Also, I am using c++11, but if there is a better way in c++14 or above, I would also like to know.










share|improve this question
























  • With a for loop.
    – tkausl
    3 hours ago










  • @tkausl Can you give an example of how that would look?
    – Lightness Races in Orbit
    3 hours ago






  • 1




    Does it need to be SFINAE-friendly? If not, I'd use a static_assert inside the body of operator(); if so, I'd go with Jans's answer until C++20, at which point I think you can put the sizeof... in a requires clause.
    – Daniel H
    2 hours ago
















6












6








6







For example, suppose I make a class like below:



template <unsigned int INPUT_SIZE>
class A{
public:
int operator()(int input, ...){ // get INPUT_SIZE-many inputs
// return sum;
}
};


I want to get input as many as INPUT_SIZE, not more or less. How can I achieve that?



Also, I am using c++11, but if there is a better way in c++14 or above, I would also like to know.










share|improve this question















For example, suppose I make a class like below:



template <unsigned int INPUT_SIZE>
class A{
public:
int operator()(int input, ...){ // get INPUT_SIZE-many inputs
// return sum;
}
};


I want to get input as many as INPUT_SIZE, not more or less. How can I achieve that?



Also, I am using c++11, but if there is a better way in c++14 or above, I would also like to know.







c++ templates






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 3 hours ago

























asked 3 hours ago









user5876164

798




798












  • With a for loop.
    – tkausl
    3 hours ago










  • @tkausl Can you give an example of how that would look?
    – Lightness Races in Orbit
    3 hours ago






  • 1




    Does it need to be SFINAE-friendly? If not, I'd use a static_assert inside the body of operator(); if so, I'd go with Jans's answer until C++20, at which point I think you can put the sizeof... in a requires clause.
    – Daniel H
    2 hours ago




















  • With a for loop.
    – tkausl
    3 hours ago










  • @tkausl Can you give an example of how that would look?
    – Lightness Races in Orbit
    3 hours ago






  • 1




    Does it need to be SFINAE-friendly? If not, I'd use a static_assert inside the body of operator(); if so, I'd go with Jans's answer until C++20, at which point I think you can put the sizeof... in a requires clause.
    – Daniel H
    2 hours ago


















With a for loop.
– tkausl
3 hours ago




With a for loop.
– tkausl
3 hours ago












@tkausl Can you give an example of how that would look?
– Lightness Races in Orbit
3 hours ago




@tkausl Can you give an example of how that would look?
– Lightness Races in Orbit
3 hours ago




1




1




Does it need to be SFINAE-friendly? If not, I'd use a static_assert inside the body of operator(); if so, I'd go with Jans's answer until C++20, at which point I think you can put the sizeof... in a requires clause.
– Daniel H
2 hours ago






Does it need to be SFINAE-friendly? If not, I'd use a static_assert inside the body of operator(); if so, I'd go with Jans's answer until C++20, at which point I think you can put the sizeof... in a requires clause.
– Daniel H
2 hours ago














1 Answer
1






active

oldest

votes


















8














Live demo 1



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
int operator ()(always_t<T, Is>...)
{
return 0;
}
};
template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>
{ };


A<2>{}(1, 2); // fine
A<2>{}(1, 2, 3); // fail


and this is a version that allows you to compute the sum of the parameters:



Live demo 2



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
constexpr int operator ()(std::tuple<always_t<T, Is>...>&& t) {
auto adder = (auto... ts) {
return (0 + ... + ts);
};
return std::apply(adder, std::move(t));
}
};

template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>{
};

constexpr int sum = A<3>{}(std::tuple(1, 4, 5));
static_assert(sum == 10);


The trick is to use a parameter pack with length N so that we can use it to expand as N times a specific type into the parameter list of A_impl::operator().



A parameter pack can expand into N repetition of the pattern that (usually) precede ...





Consider a function like:



template<class... T>
void foo(T...);


T... indicate in simple terms that it can be replaced by successive types into the parameter list of foo, one possible expansion could be foo(int, int, double, char), also notice that what preside ... is an identifier that comes from class... T.





Returning to the code, we need to generate a parameter pack, we did that through std::make_index_sequence<N>, that generate the sequence 0..(N-1) which is captured by std::size_t... Is, then we use this pack to expand the pattern always_t<T, Is> that is just an alias to T=int, this end up repeating T=int as many times as elements Is contains.



Note: ellipsis parameter ... is not the same as parameter pack.






share|improve this answer























  • Okay that's pretty neat
    – Lightness Races in Orbit
    2 hours ago






  • 1




    Is it okay if I ask how this code works? I have never used ... in practice with templates so it is hard for me to understand.
    – user5876164
    2 hours ago










  • @user5876164 I edited the answer with some explanation, hope you understand now.
    – Jans
    2 hours ago






  • 1




    decltype(std::make_index_sequence<N>{}) can be written concisely as std::make_index_sequence<N>. Less noise is better.
    – StoryTeller
    52 mins ago






  • 1




    always_t is just a an alias template, is used to allows for parameter pack Is appear on it and be used as a pack pattern.e.g always_t<int, 0> == int
    – Jans
    21 mins ago











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%2f53901207%2fis-there-a-way-to-get-a-given-number-of-inputs-where-the-number-is-given-by-a-te%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









8














Live demo 1



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
int operator ()(always_t<T, Is>...)
{
return 0;
}
};
template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>
{ };


A<2>{}(1, 2); // fine
A<2>{}(1, 2, 3); // fail


and this is a version that allows you to compute the sum of the parameters:



Live demo 2



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
constexpr int operator ()(std::tuple<always_t<T, Is>...>&& t) {
auto adder = (auto... ts) {
return (0 + ... + ts);
};
return std::apply(adder, std::move(t));
}
};

template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>{
};

constexpr int sum = A<3>{}(std::tuple(1, 4, 5));
static_assert(sum == 10);


The trick is to use a parameter pack with length N so that we can use it to expand as N times a specific type into the parameter list of A_impl::operator().



A parameter pack can expand into N repetition of the pattern that (usually) precede ...





Consider a function like:



template<class... T>
void foo(T...);


T... indicate in simple terms that it can be replaced by successive types into the parameter list of foo, one possible expansion could be foo(int, int, double, char), also notice that what preside ... is an identifier that comes from class... T.





Returning to the code, we need to generate a parameter pack, we did that through std::make_index_sequence<N>, that generate the sequence 0..(N-1) which is captured by std::size_t... Is, then we use this pack to expand the pattern always_t<T, Is> that is just an alias to T=int, this end up repeating T=int as many times as elements Is contains.



Note: ellipsis parameter ... is not the same as parameter pack.






share|improve this answer























  • Okay that's pretty neat
    – Lightness Races in Orbit
    2 hours ago






  • 1




    Is it okay if I ask how this code works? I have never used ... in practice with templates so it is hard for me to understand.
    – user5876164
    2 hours ago










  • @user5876164 I edited the answer with some explanation, hope you understand now.
    – Jans
    2 hours ago






  • 1




    decltype(std::make_index_sequence<N>{}) can be written concisely as std::make_index_sequence<N>. Less noise is better.
    – StoryTeller
    52 mins ago






  • 1




    always_t is just a an alias template, is used to allows for parameter pack Is appear on it and be used as a pack pattern.e.g always_t<int, 0> == int
    – Jans
    21 mins ago
















8














Live demo 1



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
int operator ()(always_t<T, Is>...)
{
return 0;
}
};
template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>
{ };


A<2>{}(1, 2); // fine
A<2>{}(1, 2, 3); // fail


and this is a version that allows you to compute the sum of the parameters:



Live demo 2



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
constexpr int operator ()(std::tuple<always_t<T, Is>...>&& t) {
auto adder = (auto... ts) {
return (0 + ... + ts);
};
return std::apply(adder, std::move(t));
}
};

template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>{
};

constexpr int sum = A<3>{}(std::tuple(1, 4, 5));
static_assert(sum == 10);


The trick is to use a parameter pack with length N so that we can use it to expand as N times a specific type into the parameter list of A_impl::operator().



A parameter pack can expand into N repetition of the pattern that (usually) precede ...





Consider a function like:



template<class... T>
void foo(T...);


T... indicate in simple terms that it can be replaced by successive types into the parameter list of foo, one possible expansion could be foo(int, int, double, char), also notice that what preside ... is an identifier that comes from class... T.





Returning to the code, we need to generate a parameter pack, we did that through std::make_index_sequence<N>, that generate the sequence 0..(N-1) which is captured by std::size_t... Is, then we use this pack to expand the pattern always_t<T, Is> that is just an alias to T=int, this end up repeating T=int as many times as elements Is contains.



Note: ellipsis parameter ... is not the same as parameter pack.






share|improve this answer























  • Okay that's pretty neat
    – Lightness Races in Orbit
    2 hours ago






  • 1




    Is it okay if I ask how this code works? I have never used ... in practice with templates so it is hard for me to understand.
    – user5876164
    2 hours ago










  • @user5876164 I edited the answer with some explanation, hope you understand now.
    – Jans
    2 hours ago






  • 1




    decltype(std::make_index_sequence<N>{}) can be written concisely as std::make_index_sequence<N>. Less noise is better.
    – StoryTeller
    52 mins ago






  • 1




    always_t is just a an alias template, is used to allows for parameter pack Is appear on it and be used as a pack pattern.e.g always_t<int, 0> == int
    – Jans
    21 mins ago














8












8








8






Live demo 1



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
int operator ()(always_t<T, Is>...)
{
return 0;
}
};
template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>
{ };


A<2>{}(1, 2); // fine
A<2>{}(1, 2, 3); // fail


and this is a version that allows you to compute the sum of the parameters:



Live demo 2



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
constexpr int operator ()(std::tuple<always_t<T, Is>...>&& t) {
auto adder = (auto... ts) {
return (0 + ... + ts);
};
return std::apply(adder, std::move(t));
}
};

template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>{
};

constexpr int sum = A<3>{}(std::tuple(1, 4, 5));
static_assert(sum == 10);


The trick is to use a parameter pack with length N so that we can use it to expand as N times a specific type into the parameter list of A_impl::operator().



A parameter pack can expand into N repetition of the pattern that (usually) precede ...





Consider a function like:



template<class... T>
void foo(T...);


T... indicate in simple terms that it can be replaced by successive types into the parameter list of foo, one possible expansion could be foo(int, int, double, char), also notice that what preside ... is an identifier that comes from class... T.





Returning to the code, we need to generate a parameter pack, we did that through std::make_index_sequence<N>, that generate the sequence 0..(N-1) which is captured by std::size_t... Is, then we use this pack to expand the pattern always_t<T, Is> that is just an alias to T=int, this end up repeating T=int as many times as elements Is contains.



Note: ellipsis parameter ... is not the same as parameter pack.






share|improve this answer














Live demo 1



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
int operator ()(always_t<T, Is>...)
{
return 0;
}
};
template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>
{ };


A<2>{}(1, 2); // fine
A<2>{}(1, 2, 3); // fail


and this is a version that allows you to compute the sum of the parameters:



Live demo 2



template <class T, auto> using always_t = T;

template <class T, class Arity>
struct A_impl;

template <class T, std::size_t... Is>
struct A_impl<T, std::index_sequence<Is...>>
{
constexpr int operator ()(std::tuple<always_t<T, Is>...>&& t) {
auto adder = (auto... ts) {
return (0 + ... + ts);
};
return std::apply(adder, std::move(t));
}
};

template <std::size_t N>
struct A : A_impl<int, std::make_index_sequence<N>>{
};

constexpr int sum = A<3>{}(std::tuple(1, 4, 5));
static_assert(sum == 10);


The trick is to use a parameter pack with length N so that we can use it to expand as N times a specific type into the parameter list of A_impl::operator().



A parameter pack can expand into N repetition of the pattern that (usually) precede ...





Consider a function like:



template<class... T>
void foo(T...);


T... indicate in simple terms that it can be replaced by successive types into the parameter list of foo, one possible expansion could be foo(int, int, double, char), also notice that what preside ... is an identifier that comes from class... T.





Returning to the code, we need to generate a parameter pack, we did that through std::make_index_sequence<N>, that generate the sequence 0..(N-1) which is captured by std::size_t... Is, then we use this pack to expand the pattern always_t<T, Is> that is just an alias to T=int, this end up repeating T=int as many times as elements Is contains.



Note: ellipsis parameter ... is not the same as parameter pack.







share|improve this answer














share|improve this answer



share|improve this answer








edited 28 mins ago

























answered 2 hours ago









Jans

7,39422233




7,39422233












  • Okay that's pretty neat
    – Lightness Races in Orbit
    2 hours ago






  • 1




    Is it okay if I ask how this code works? I have never used ... in practice with templates so it is hard for me to understand.
    – user5876164
    2 hours ago










  • @user5876164 I edited the answer with some explanation, hope you understand now.
    – Jans
    2 hours ago






  • 1




    decltype(std::make_index_sequence<N>{}) can be written concisely as std::make_index_sequence<N>. Less noise is better.
    – StoryTeller
    52 mins ago






  • 1




    always_t is just a an alias template, is used to allows for parameter pack Is appear on it and be used as a pack pattern.e.g always_t<int, 0> == int
    – Jans
    21 mins ago


















  • Okay that's pretty neat
    – Lightness Races in Orbit
    2 hours ago






  • 1




    Is it okay if I ask how this code works? I have never used ... in practice with templates so it is hard for me to understand.
    – user5876164
    2 hours ago










  • @user5876164 I edited the answer with some explanation, hope you understand now.
    – Jans
    2 hours ago






  • 1




    decltype(std::make_index_sequence<N>{}) can be written concisely as std::make_index_sequence<N>. Less noise is better.
    – StoryTeller
    52 mins ago






  • 1




    always_t is just a an alias template, is used to allows for parameter pack Is appear on it and be used as a pack pattern.e.g always_t<int, 0> == int
    – Jans
    21 mins ago
















Okay that's pretty neat
– Lightness Races in Orbit
2 hours ago




Okay that's pretty neat
– Lightness Races in Orbit
2 hours ago




1




1




Is it okay if I ask how this code works? I have never used ... in practice with templates so it is hard for me to understand.
– user5876164
2 hours ago




Is it okay if I ask how this code works? I have never used ... in practice with templates so it is hard for me to understand.
– user5876164
2 hours ago












@user5876164 I edited the answer with some explanation, hope you understand now.
– Jans
2 hours ago




@user5876164 I edited the answer with some explanation, hope you understand now.
– Jans
2 hours ago




1




1




decltype(std::make_index_sequence<N>{}) can be written concisely as std::make_index_sequence<N>. Less noise is better.
– StoryTeller
52 mins ago




decltype(std::make_index_sequence<N>{}) can be written concisely as std::make_index_sequence<N>. Less noise is better.
– StoryTeller
52 mins ago




1




1




always_t is just a an alias template, is used to allows for parameter pack Is appear on it and be used as a pack pattern.e.g always_t<int, 0> == int
– Jans
21 mins ago




always_t is just a an alias template, is used to allows for parameter pack Is appear on it and be used as a pack pattern.e.g always_t<int, 0> == int
– Jans
21 mins ago


















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.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • 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%2f53901207%2fis-there-a-way-to-get-a-given-number-of-inputs-where-the-number-is-given-by-a-te%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

How did Captain America manage to do this?

迪纳利

南乌拉尔铁路局