I'm working on a C 14 project and I just wrote a function with parameter pack.
template <typename... Args>
void func(Args&&... args) {
...
}
The args
should contain only int
or std::string
, it can't be any other types.
Is there any way to do the check at compile time? Maybe something as below?
template <typename... Args, std::enable_if_t<???* = nullptr>
void func(Args&&... args) {
...
}
CodePudding user response:
This gets better with folds in C 17 and concepts in C 20, but you can test each element against int
and std::string
.
The first end of the recursion is the primary template. If no specialisation matches, we are false.
template <typename... Ts>
struct all_int_or_string : std::false_type {};
The other end of recursion is the empty pack, which is true.
template <>
all_int_or_string<> : std::true_type {};
If we find int
or std::string
as the first element, recurse the remaining elements
template <typename... Ts>
struct all_int_or_string<int, Ts...> : all_int_or_string<Ts...> {}
template <typename... Ts>
struct all_int_or_string<std::string, Ts...> : all_int_or_string<Ts...> {}
You probably also want to strip off qualifiers.
template <typename T, typename... Ts>
struct all_int_or_string<const T, Ts...> : all_int_or_string<T, Ts...> {}
template <typename T, typename... Ts>
struct all_int_or_string<volatile T, Ts...> : all_int_or_string<T, Ts...> {}
template <typename T, typename... Ts>
struct all_int_or_string<T &, Ts...> : all_int_or_string<T, Ts...> {}
template <typename T, typename... Ts>
struct all_int_or_string<T &&, Ts...> : all_int_or_string<T, Ts...> {}
Used thusly
template <typename... Args, std::enable_if_t<all_int_or_string<Args...>::value>* = nullptr>
void func(Args&&... args) {
}