Is there a way to get a given number of inputs where the number is given by a template in compile time in c++?
Clash Royale CLAN TAG#URR8PPP
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
add a comment |
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
With a for loop.
– tkausl
Dec 23 '18 at 4:30
@tkausl Can you give an example of how that would look?
– Lightness Races in Orbit
Dec 23 '18 at 4:34
3
Does it need to be SFINAE-friendly? If not, I'd use astatic_assert
inside the body ofoperator()
; if so, I'd go with Jans's answer until C++20, at which point I think you can put thesizeof...
in arequires
clause.
– Daniel H
Dec 23 '18 at 4:50
1
See also: Number of Variadic Template Function Parameters?
– user202729
Dec 23 '18 at 9:27
add a comment |
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
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
c++ templates
edited Dec 23 '18 at 4:32
asked Dec 23 '18 at 4:29
user5876164
848
848
With a for loop.
– tkausl
Dec 23 '18 at 4:30
@tkausl Can you give an example of how that would look?
– Lightness Races in Orbit
Dec 23 '18 at 4:34
3
Does it need to be SFINAE-friendly? If not, I'd use astatic_assert
inside the body ofoperator()
; if so, I'd go with Jans's answer until C++20, at which point I think you can put thesizeof...
in arequires
clause.
– Daniel H
Dec 23 '18 at 4:50
1
See also: Number of Variadic Template Function Parameters?
– user202729
Dec 23 '18 at 9:27
add a comment |
With a for loop.
– tkausl
Dec 23 '18 at 4:30
@tkausl Can you give an example of how that would look?
– Lightness Races in Orbit
Dec 23 '18 at 4:34
3
Does it need to be SFINAE-friendly? If not, I'd use astatic_assert
inside the body ofoperator()
; if so, I'd go with Jans's answer until C++20, at which point I think you can put thesizeof...
in arequires
clause.
– Daniel H
Dec 23 '18 at 4:50
1
See also: Number of Variadic Template Function Parameters?
– user202729
Dec 23 '18 at 9:27
With a for loop.
– tkausl
Dec 23 '18 at 4:30
With a for loop.
– tkausl
Dec 23 '18 at 4:30
@tkausl Can you give an example of how that would look?
– Lightness Races in Orbit
Dec 23 '18 at 4:34
@tkausl Can you give an example of how that would look?
– Lightness Races in Orbit
Dec 23 '18 at 4:34
3
3
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
Dec 23 '18 at 4:50
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
Dec 23 '18 at 4:50
1
1
See also: Number of Variadic Template Function Parameters?
– user202729
Dec 23 '18 at 9:27
See also: Number of Variadic Template Function Parameters?
– user202729
Dec 23 '18 at 9:27
add a comment |
1 Answer
1
active
oldest
votes
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>(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.
Okay that's pretty neat
– Lightness Races in Orbit
Dec 23 '18 at 4:47
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
Dec 23 '18 at 4:58
1
decltype(std::make_index_sequence<N>)
can be written concisely asstd::make_index_sequence<N>
. Less noise is better.
– StoryTeller
Dec 23 '18 at 6:47
1
always_t
is just a an alias template, is used to allows for parameter packIs
appear on it and be used as a pack pattern.e.galways_t<int, 0> == int
– Jans
Dec 23 '18 at 7:18
1
Note that all that examples use C++17, but can be rewritten in C++11 with relative small changes.
– Jarod42
Dec 23 '18 at 8:25
|
show 3 more comments
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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>(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.
Okay that's pretty neat
– Lightness Races in Orbit
Dec 23 '18 at 4:47
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
Dec 23 '18 at 4:58
1
decltype(std::make_index_sequence<N>)
can be written concisely asstd::make_index_sequence<N>
. Less noise is better.
– StoryTeller
Dec 23 '18 at 6:47
1
always_t
is just a an alias template, is used to allows for parameter packIs
appear on it and be used as a pack pattern.e.galways_t<int, 0> == int
– Jans
Dec 23 '18 at 7:18
1
Note that all that examples use C++17, but can be rewritten in C++11 with relative small changes.
– Jarod42
Dec 23 '18 at 8:25
|
show 3 more comments
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>(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.
Okay that's pretty neat
– Lightness Races in Orbit
Dec 23 '18 at 4:47
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
Dec 23 '18 at 4:58
1
decltype(std::make_index_sequence<N>)
can be written concisely asstd::make_index_sequence<N>
. Less noise is better.
– StoryTeller
Dec 23 '18 at 6:47
1
always_t
is just a an alias template, is used to allows for parameter packIs
appear on it and be used as a pack pattern.e.galways_t<int, 0> == int
– Jans
Dec 23 '18 at 7:18
1
Note that all that examples use C++17, but can be rewritten in C++11 with relative small changes.
– Jarod42
Dec 23 '18 at 8:25
|
show 3 more comments
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>(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.
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>(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.
edited Dec 23 '18 at 15:39
answered Dec 23 '18 at 4:45
Jans
8,40522635
8,40522635
Okay that's pretty neat
– Lightness Races in Orbit
Dec 23 '18 at 4:47
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
Dec 23 '18 at 4:58
1
decltype(std::make_index_sequence<N>)
can be written concisely asstd::make_index_sequence<N>
. Less noise is better.
– StoryTeller
Dec 23 '18 at 6:47
1
always_t
is just a an alias template, is used to allows for parameter packIs
appear on it and be used as a pack pattern.e.galways_t<int, 0> == int
– Jans
Dec 23 '18 at 7:18
1
Note that all that examples use C++17, but can be rewritten in C++11 with relative small changes.
– Jarod42
Dec 23 '18 at 8:25
|
show 3 more comments
Okay that's pretty neat
– Lightness Races in Orbit
Dec 23 '18 at 4:47
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
Dec 23 '18 at 4:58
1
decltype(std::make_index_sequence<N>)
can be written concisely asstd::make_index_sequence<N>
. Less noise is better.
– StoryTeller
Dec 23 '18 at 6:47
1
always_t
is just a an alias template, is used to allows for parameter packIs
appear on it and be used as a pack pattern.e.galways_t<int, 0> == int
– Jans
Dec 23 '18 at 7:18
1
Note that all that examples use C++17, but can be rewritten in C++11 with relative small changes.
– Jarod42
Dec 23 '18 at 8:25
Okay that's pretty neat
– Lightness Races in Orbit
Dec 23 '18 at 4:47
Okay that's pretty neat
– Lightness Races in Orbit
Dec 23 '18 at 4:47
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
Dec 23 '18 at 4:58
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
Dec 23 '18 at 4:58
1
1
decltype(std::make_index_sequence<N>)
can be written concisely as std::make_index_sequence<N>
. Less noise is better.– StoryTeller
Dec 23 '18 at 6:47
decltype(std::make_index_sequence<N>)
can be written concisely as std::make_index_sequence<N>
. Less noise is better.– StoryTeller
Dec 23 '18 at 6:47
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
Dec 23 '18 at 7:18
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
Dec 23 '18 at 7:18
1
1
Note that all that examples use C++17, but can be rewritten in C++11 with relative small changes.
– Jarod42
Dec 23 '18 at 8:25
Note that all that examples use C++17, but can be rewritten in C++11 with relative small changes.
– Jarod42
Dec 23 '18 at 8:25
|
show 3 more comments
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
With a for loop.
– tkausl
Dec 23 '18 at 4:30
@tkausl Can you give an example of how that would look?
– Lightness Races in Orbit
Dec 23 '18 at 4:34
3
Does it need to be SFINAE-friendly? If not, I'd use a
static_assert
inside the body ofoperator()
; if so, I'd go with Jans's answer until C++20, at which point I think you can put thesizeof...
in arequires
clause.– Daniel H
Dec 23 '18 at 4:50
1
See also: Number of Variadic Template Function Parameters?
– user202729
Dec 23 '18 at 9:27