unpacking values of an array as parameters to a variadic function
I am trying (at compile time) to unpack integers as arguments to a variadic function. The idea would be to have those values packed in an array or in a std::index_sequence
(c++14) at compile time. I have tried to use some of the answers from older posts, but I find the example code unreadable for my level.
Here is a simple example with the functionality that I need to implement in a code that I am writing, in this case attempting to use std::make_index_sequence
. I do not necessarily need to use the latter. The problem is that the values of the sequence are not unpacked as arguments to the variadic function:
#include <cstdio>
#include <iostream>
#include <utility>
using namespace std;
void print(const int &val){
cout << val << endl;
}
template<typename ...S> void print(const int &val, const S&... others)
{
print(val);
print(others...);
}
template<size_t n> void printNumbers(){
std::make_index_sequence<n> a;
print(a);
}
int main(){
printNumbers<6>();
}
The output from GCC8:
tet.cc: In instantiation of ‘void printNumbers() [with long unsigned int n = 6]’:
tet.cc:25:19: required from here
tet.cc:20:8: error: no matching function for call to ‘print(std::make_index_sequence<6>&)’
print(a);
~~~~~^~~
tet.cc:8:6: note: candidate: ‘void print(const int&)’
void print(const int &val){
^~~~~
tet.cc:8:6: note: no known conversion for argument 1 from ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’} to ‘const int&’
tet.cc:12:30: note: candidate: ‘template<class ... S> void print(const int&, const S& ...)’
template<typename ...S> void print(const int &val, const S&... others)
^~~~~
tet.cc:12:30: note: template argument deduction/substitution failed:
tet.cc:20:9: note: cannot convert ‘a’ (type ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’}) to type ‘const int&’
c++ c++11 c++14 variadic-templates template-meta-programming
add a comment |
I am trying (at compile time) to unpack integers as arguments to a variadic function. The idea would be to have those values packed in an array or in a std::index_sequence
(c++14) at compile time. I have tried to use some of the answers from older posts, but I find the example code unreadable for my level.
Here is a simple example with the functionality that I need to implement in a code that I am writing, in this case attempting to use std::make_index_sequence
. I do not necessarily need to use the latter. The problem is that the values of the sequence are not unpacked as arguments to the variadic function:
#include <cstdio>
#include <iostream>
#include <utility>
using namespace std;
void print(const int &val){
cout << val << endl;
}
template<typename ...S> void print(const int &val, const S&... others)
{
print(val);
print(others...);
}
template<size_t n> void printNumbers(){
std::make_index_sequence<n> a;
print(a);
}
int main(){
printNumbers<6>();
}
The output from GCC8:
tet.cc: In instantiation of ‘void printNumbers() [with long unsigned int n = 6]’:
tet.cc:25:19: required from here
tet.cc:20:8: error: no matching function for call to ‘print(std::make_index_sequence<6>&)’
print(a);
~~~~~^~~
tet.cc:8:6: note: candidate: ‘void print(const int&)’
void print(const int &val){
^~~~~
tet.cc:8:6: note: no known conversion for argument 1 from ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’} to ‘const int&’
tet.cc:12:30: note: candidate: ‘template<class ... S> void print(const int&, const S& ...)’
template<typename ...S> void print(const int &val, const S&... others)
^~~~~
tet.cc:12:30: note: template argument deduction/substitution failed:
tet.cc:20:9: note: cannot convert ‘a’ (type ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’}) to type ‘const int&’
c++ c++11 c++14 variadic-templates template-meta-programming
add a comment |
I am trying (at compile time) to unpack integers as arguments to a variadic function. The idea would be to have those values packed in an array or in a std::index_sequence
(c++14) at compile time. I have tried to use some of the answers from older posts, but I find the example code unreadable for my level.
Here is a simple example with the functionality that I need to implement in a code that I am writing, in this case attempting to use std::make_index_sequence
. I do not necessarily need to use the latter. The problem is that the values of the sequence are not unpacked as arguments to the variadic function:
#include <cstdio>
#include <iostream>
#include <utility>
using namespace std;
void print(const int &val){
cout << val << endl;
}
template<typename ...S> void print(const int &val, const S&... others)
{
print(val);
print(others...);
}
template<size_t n> void printNumbers(){
std::make_index_sequence<n> a;
print(a);
}
int main(){
printNumbers<6>();
}
The output from GCC8:
tet.cc: In instantiation of ‘void printNumbers() [with long unsigned int n = 6]’:
tet.cc:25:19: required from here
tet.cc:20:8: error: no matching function for call to ‘print(std::make_index_sequence<6>&)’
print(a);
~~~~~^~~
tet.cc:8:6: note: candidate: ‘void print(const int&)’
void print(const int &val){
^~~~~
tet.cc:8:6: note: no known conversion for argument 1 from ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’} to ‘const int&’
tet.cc:12:30: note: candidate: ‘template<class ... S> void print(const int&, const S& ...)’
template<typename ...S> void print(const int &val, const S&... others)
^~~~~
tet.cc:12:30: note: template argument deduction/substitution failed:
tet.cc:20:9: note: cannot convert ‘a’ (type ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’}) to type ‘const int&’
c++ c++11 c++14 variadic-templates template-meta-programming
I am trying (at compile time) to unpack integers as arguments to a variadic function. The idea would be to have those values packed in an array or in a std::index_sequence
(c++14) at compile time. I have tried to use some of the answers from older posts, but I find the example code unreadable for my level.
Here is a simple example with the functionality that I need to implement in a code that I am writing, in this case attempting to use std::make_index_sequence
. I do not necessarily need to use the latter. The problem is that the values of the sequence are not unpacked as arguments to the variadic function:
#include <cstdio>
#include <iostream>
#include <utility>
using namespace std;
void print(const int &val){
cout << val << endl;
}
template<typename ...S> void print(const int &val, const S&... others)
{
print(val);
print(others...);
}
template<size_t n> void printNumbers(){
std::make_index_sequence<n> a;
print(a);
}
int main(){
printNumbers<6>();
}
The output from GCC8:
tet.cc: In instantiation of ‘void printNumbers() [with long unsigned int n = 6]’:
tet.cc:25:19: required from here
tet.cc:20:8: error: no matching function for call to ‘print(std::make_index_sequence<6>&)’
print(a);
~~~~~^~~
tet.cc:8:6: note: candidate: ‘void print(const int&)’
void print(const int &val){
^~~~~
tet.cc:8:6: note: no known conversion for argument 1 from ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’} to ‘const int&’
tet.cc:12:30: note: candidate: ‘template<class ... S> void print(const int&, const S& ...)’
template<typename ...S> void print(const int &val, const S&... others)
^~~~~
tet.cc:12:30: note: template argument deduction/substitution failed:
tet.cc:20:9: note: cannot convert ‘a’ (type ‘std::make_index_sequence<6>’ {aka ‘std::integer_sequence<long unsigned int, 0, 1, 2, 3, 4, 5>’}) to type ‘const int&’
c++ c++11 c++14 variadic-templates template-meta-programming
c++ c++11 c++14 variadic-templates template-meta-programming
edited Nov 24 '18 at 11:08
max66
36.5k74165
36.5k74165
asked Nov 24 '18 at 9:03
JdlCRJdlCR
454
454
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
std::make_index_sequence<6>
is an alias for:
std::integer_sequence<std::size_t, 0, 1, 2, 3, 4, 5>
and this is the type of the expression a
that is the argument of the function call print(a)
. Your print
function expects individual values, not an std::integer_sequence
.
To make your implementation work, you should first deduce the indices, and only then use them as arguments for print
:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
print(Is...);
}
template <std::size_t N>
void printNumbers()
{
printNumbers(std::make_index_sequence<N>{});
}
In c++17 you could remove the intermediate print
function and just say:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
(print(Is), ...);
}
In c++20 you can both create an index sequence and deduce its indices within a single function:
template <std::size_t N>
void printNumbers()
{
<std::size_t... Is> (std::index_sequence<Is...>)
{ (print(Is), ...); }(std::make_index_sequence<N>{});
}
DEMO
add a comment |
As an addendum to the Piotr Skotnicki's answer, I propose a C++14 way to avoid the recursive print()
.
Not so elegant as the C++17 solution, based on template folding, but equally permit to avoid the use of recursion (and consider that template recursion is usually strict limited by compilers, so the recursive solution works but not when N
exceed the recursion limit).
You have to write the printNumber()
function as usual, passing a std::make_index_sequence<N>
(that inherit from std::index_sequence<0, 1, ...., N-1>
aka std::integer_sequence<std::size_t, 0, 1, ..., N-1>
) to another function
template <std::size_t N>
void printNumbers ()
{ printNumbers2(std::make_index_sequence<N>{}); }
but in the printNumbers2()
you can avoid to call the recursive print()
and you can call the print()
that effectively call std::cout
inside the initialization of an unused array
template <std::size_t ... Is>
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (print(Is), 0)... };
}
You can also avoid both print()
functions printing directly in printNumbers2()
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (std::cout << val << std::endl, 0)... };
}
You can do the same in the C++17/C++20 template folding solutions.
In C++11 this solution doesn't works but only because std::make_integer_sequence
and std::index_sequence
are introduced from C++11.
If you write a C++11 surrogate for std::make_integer_sequence
and std::index_sequence
, you can adapt this solution also to C++11.
add a comment |
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%2f53456688%2funpacking-values-of-an-array-as-parameters-to-a-variadic-function%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
std::make_index_sequence<6>
is an alias for:
std::integer_sequence<std::size_t, 0, 1, 2, 3, 4, 5>
and this is the type of the expression a
that is the argument of the function call print(a)
. Your print
function expects individual values, not an std::integer_sequence
.
To make your implementation work, you should first deduce the indices, and only then use them as arguments for print
:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
print(Is...);
}
template <std::size_t N>
void printNumbers()
{
printNumbers(std::make_index_sequence<N>{});
}
In c++17 you could remove the intermediate print
function and just say:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
(print(Is), ...);
}
In c++20 you can both create an index sequence and deduce its indices within a single function:
template <std::size_t N>
void printNumbers()
{
<std::size_t... Is> (std::index_sequence<Is...>)
{ (print(Is), ...); }(std::make_index_sequence<N>{});
}
DEMO
add a comment |
std::make_index_sequence<6>
is an alias for:
std::integer_sequence<std::size_t, 0, 1, 2, 3, 4, 5>
and this is the type of the expression a
that is the argument of the function call print(a)
. Your print
function expects individual values, not an std::integer_sequence
.
To make your implementation work, you should first deduce the indices, and only then use them as arguments for print
:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
print(Is...);
}
template <std::size_t N>
void printNumbers()
{
printNumbers(std::make_index_sequence<N>{});
}
In c++17 you could remove the intermediate print
function and just say:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
(print(Is), ...);
}
In c++20 you can both create an index sequence and deduce its indices within a single function:
template <std::size_t N>
void printNumbers()
{
<std::size_t... Is> (std::index_sequence<Is...>)
{ (print(Is), ...); }(std::make_index_sequence<N>{});
}
DEMO
add a comment |
std::make_index_sequence<6>
is an alias for:
std::integer_sequence<std::size_t, 0, 1, 2, 3, 4, 5>
and this is the type of the expression a
that is the argument of the function call print(a)
. Your print
function expects individual values, not an std::integer_sequence
.
To make your implementation work, you should first deduce the indices, and only then use them as arguments for print
:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
print(Is...);
}
template <std::size_t N>
void printNumbers()
{
printNumbers(std::make_index_sequence<N>{});
}
In c++17 you could remove the intermediate print
function and just say:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
(print(Is), ...);
}
In c++20 you can both create an index sequence and deduce its indices within a single function:
template <std::size_t N>
void printNumbers()
{
<std::size_t... Is> (std::index_sequence<Is...>)
{ (print(Is), ...); }(std::make_index_sequence<N>{});
}
DEMO
std::make_index_sequence<6>
is an alias for:
std::integer_sequence<std::size_t, 0, 1, 2, 3, 4, 5>
and this is the type of the expression a
that is the argument of the function call print(a)
. Your print
function expects individual values, not an std::integer_sequence
.
To make your implementation work, you should first deduce the indices, and only then use them as arguments for print
:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
print(Is...);
}
template <std::size_t N>
void printNumbers()
{
printNumbers(std::make_index_sequence<N>{});
}
In c++17 you could remove the intermediate print
function and just say:
template <std::size_t... Is>
void printNumbers(std::index_sequence<Is...>)
{
(print(Is), ...);
}
In c++20 you can both create an index sequence and deduce its indices within a single function:
template <std::size_t N>
void printNumbers()
{
<std::size_t... Is> (std::index_sequence<Is...>)
{ (print(Is), ...); }(std::make_index_sequence<N>{});
}
DEMO
edited Nov 24 '18 at 10:04
answered Nov 24 '18 at 9:12
Piotr SkotnickiPiotr Skotnicki
34.8k472118
34.8k472118
add a comment |
add a comment |
As an addendum to the Piotr Skotnicki's answer, I propose a C++14 way to avoid the recursive print()
.
Not so elegant as the C++17 solution, based on template folding, but equally permit to avoid the use of recursion (and consider that template recursion is usually strict limited by compilers, so the recursive solution works but not when N
exceed the recursion limit).
You have to write the printNumber()
function as usual, passing a std::make_index_sequence<N>
(that inherit from std::index_sequence<0, 1, ...., N-1>
aka std::integer_sequence<std::size_t, 0, 1, ..., N-1>
) to another function
template <std::size_t N>
void printNumbers ()
{ printNumbers2(std::make_index_sequence<N>{}); }
but in the printNumbers2()
you can avoid to call the recursive print()
and you can call the print()
that effectively call std::cout
inside the initialization of an unused array
template <std::size_t ... Is>
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (print(Is), 0)... };
}
You can also avoid both print()
functions printing directly in printNumbers2()
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (std::cout << val << std::endl, 0)... };
}
You can do the same in the C++17/C++20 template folding solutions.
In C++11 this solution doesn't works but only because std::make_integer_sequence
and std::index_sequence
are introduced from C++11.
If you write a C++11 surrogate for std::make_integer_sequence
and std::index_sequence
, you can adapt this solution also to C++11.
add a comment |
As an addendum to the Piotr Skotnicki's answer, I propose a C++14 way to avoid the recursive print()
.
Not so elegant as the C++17 solution, based on template folding, but equally permit to avoid the use of recursion (and consider that template recursion is usually strict limited by compilers, so the recursive solution works but not when N
exceed the recursion limit).
You have to write the printNumber()
function as usual, passing a std::make_index_sequence<N>
(that inherit from std::index_sequence<0, 1, ...., N-1>
aka std::integer_sequence<std::size_t, 0, 1, ..., N-1>
) to another function
template <std::size_t N>
void printNumbers ()
{ printNumbers2(std::make_index_sequence<N>{}); }
but in the printNumbers2()
you can avoid to call the recursive print()
and you can call the print()
that effectively call std::cout
inside the initialization of an unused array
template <std::size_t ... Is>
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (print(Is), 0)... };
}
You can also avoid both print()
functions printing directly in printNumbers2()
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (std::cout << val << std::endl, 0)... };
}
You can do the same in the C++17/C++20 template folding solutions.
In C++11 this solution doesn't works but only because std::make_integer_sequence
and std::index_sequence
are introduced from C++11.
If you write a C++11 surrogate for std::make_integer_sequence
and std::index_sequence
, you can adapt this solution also to C++11.
add a comment |
As an addendum to the Piotr Skotnicki's answer, I propose a C++14 way to avoid the recursive print()
.
Not so elegant as the C++17 solution, based on template folding, but equally permit to avoid the use of recursion (and consider that template recursion is usually strict limited by compilers, so the recursive solution works but not when N
exceed the recursion limit).
You have to write the printNumber()
function as usual, passing a std::make_index_sequence<N>
(that inherit from std::index_sequence<0, 1, ...., N-1>
aka std::integer_sequence<std::size_t, 0, 1, ..., N-1>
) to another function
template <std::size_t N>
void printNumbers ()
{ printNumbers2(std::make_index_sequence<N>{}); }
but in the printNumbers2()
you can avoid to call the recursive print()
and you can call the print()
that effectively call std::cout
inside the initialization of an unused array
template <std::size_t ... Is>
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (print(Is), 0)... };
}
You can also avoid both print()
functions printing directly in printNumbers2()
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (std::cout << val << std::endl, 0)... };
}
You can do the same in the C++17/C++20 template folding solutions.
In C++11 this solution doesn't works but only because std::make_integer_sequence
and std::index_sequence
are introduced from C++11.
If you write a C++11 surrogate for std::make_integer_sequence
and std::index_sequence
, you can adapt this solution also to C++11.
As an addendum to the Piotr Skotnicki's answer, I propose a C++14 way to avoid the recursive print()
.
Not so elegant as the C++17 solution, based on template folding, but equally permit to avoid the use of recursion (and consider that template recursion is usually strict limited by compilers, so the recursive solution works but not when N
exceed the recursion limit).
You have to write the printNumber()
function as usual, passing a std::make_index_sequence<N>
(that inherit from std::index_sequence<0, 1, ...., N-1>
aka std::integer_sequence<std::size_t, 0, 1, ..., N-1>
) to another function
template <std::size_t N>
void printNumbers ()
{ printNumbers2(std::make_index_sequence<N>{}); }
but in the printNumbers2()
you can avoid to call the recursive print()
and you can call the print()
that effectively call std::cout
inside the initialization of an unused array
template <std::size_t ... Is>
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (print(Is), 0)... };
}
You can also avoid both print()
functions printing directly in printNumbers2()
void printNumbers2 (std::index_sequence<Is...>)
{
using unused = int;
(void)unused { 0, (std::cout << val << std::endl, 0)... };
}
You can do the same in the C++17/C++20 template folding solutions.
In C++11 this solution doesn't works but only because std::make_integer_sequence
and std::index_sequence
are introduced from C++11.
If you write a C++11 surrogate for std::make_integer_sequence
and std::index_sequence
, you can adapt this solution also to C++11.
answered Nov 24 '18 at 10:46
max66max66
36.5k74165
36.5k74165
add a comment |
add a comment |
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.
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%2f53456688%2funpacking-values-of-an-array-as-parameters-to-a-variadic-function%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