Reputation: 551
Is it possible to statically "unroll" a parameter list at compile time, giving using one parameter in every "unroll" step? I think variadic templates are the way to go combined with partial template specialization, but I cannot get this example to run:
#include <iostream>
char static const text1[] = "Foo";
char static const text2[] = "FooBar";
template <char const * TEXT, unsigned int N, char const *... REST, unsigned int... Ns>
void doStuff() {
std :: cout << TEXT << "-" << N << std :: endl;
doStuff<REST..., Ns...>();
}
template <char const * TEXT, unsigned int N>
void doStuff() {
std :: cout << TEXT << std :: endl;
}
void doStuff() {}
int main() {
doStuff<text1,3,text2,5>();
return 0;
}
My expected output would be Foo-3\nFooBar-5
However, clang++ 3.8 gives me:
error: no matching function for call to 'doStuff'
doStuff<text1,3,text2,5>();
^~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:7:6: note: candidate template ignored: invalid explicitly-specified argument for template
parameter 'REST'
void doStuff() {
^
test.cpp:13:6: note: candidate template ignored: invalid explicitly-specified argument for template
parameter 'N'
void doStuff() {
^
Upvotes: 4
Views: 4316
Reputation: 217428
In C++17, you might do something like
template <char const * TEXT, unsigned int N>
void doStuff() {
std::cout << TEXT << "-" << N << std::endl;
}
template <auto v1, auto v2, auto ... values>
void doStuff()
{
std :: cout << v1 << "-" << v2 << std :: endl;
doStuff<values...>();
}
Currently you have to pack your values by pair:
template<const char* S, int N>
struct pairValue {
static constexpr const char* s = S;
static constexpr int n = N;
};
template <typename ... Ts>
void doStuff()
{
const int dummy[] = {0, ((std::cout << Ts::s << "-" << Ts::n << std::endl), 0)...};
static_cast<void>(dummy); // Avoid warning for unused variable.
}
And call it:
doStuff<pairValue<text1, 3>, pairValue<text2, 5>>();
Upvotes: 2
Reputation: 50550
You can use them as parameters to work around it:
#include <iostream>
#include<type_traits>
char static const text1[] = "Foo";
char static const text2[] = "FooBar";
constexpr void doStuff() {}
template <typename T, typename U, typename... O>
constexpr
std::enable_if_t<
std::is_same<T, const char *>::value
and std::is_same<U, int>::value
> doStuff(T str, U num, O... o) {
std :: cout << str << "-" << num << std :: endl;
doStuff(o...);
}
int main() {
doStuff(text1,3,text2,5);
return 0;
}
Upvotes: 0