I want to unpack a variadic template pack and select a particular overload based on each type in the pack.
I have 3 overloads for unpacking various types:
// fixed size char arrays
template<size_t N, typename... Ts>
void unpack(const char (&)[N], Ts&&... ts);
// char pointers
template<typename... Ts>
void unpack(const char*, Ts&&... ts);
// all other types
template<typename T, typename... Ts>
void unpack(T&&, Ts&&... ts);
I'm passing a char array (char buf[1024]
) as an lvalue to the variadic constructor. When unpacking the pack, the T&&
overload is being selected.
How can I get the const char (&)[N]
or const char*
overload selected?
Example app:
#include <iostream>
struct foo
{
template<typename... Ts>
foo(Ts&&... ts)
{
unpack(std::forward<Ts>(ts)...);
}
template<size_t N, typename... Ts>
void unpack(const char (&)[N], Ts&&... ts)
{
std::cout << "const T (&)[N]" << std::endl;
unpack(std::forward<Ts>(ts)...);
}
template<typename... Ts>
void unpack(const char*, Ts&&... ts)
{
std::cout << "const char*" << std::endl;
unpack(std::forward<Ts>(ts)...);
}
template<typename T, typename... Ts>
void unpack(T&&, Ts&&... ts)
{
std::cout << "T&&" << std::endl;
unpack(std::forward<Ts>(ts)...);
}
void unpack()
{
}
};
int main()
{
char buf[1024];
const char* str = "foo";
foo f(buf, str);
return 0;
}
The above code results in the following being printed:
T&&
const char*
I would like it to print either:
const T (&)[N]
const char*
or
const char*
const char*
ie: select one of the two char overloads - array or pointer.
One possibility is removing the array overload and just use
template<typename T, typename... Ts>
std::enable_if_t<std::is_same<std::decay_t<T>, char>::value> unpack(T*, Ts&&... ts)
{
std::cout << "(const) char*" << std::endl;
unpack(std::forward<Ts>(ts)...);
}
This is enabled only if T
is deduced to be (possibly cv-qualified) char
(meaning it's a perfect match for both char *
and const char *
as the first parameter), and in those cases it's more specialized than the base template, and hence selected by overload resolution.
Replace enable_if_t
and decay_t
with the more verbose typename /*...*/::type
if not using C++14.
Demo.