Is it possible to write a function template which returns whether the number of arguments is divisible by N?
I've been learning about variadic templates, and with the help of this excellent blog post, I've managed to write a function template even_number_of_args
which returns whether the number of arguments it receives is divisible by 2.
#include <iostream>
bool even_number_of_args() {
return true;
}
template <typename T>
bool even_number_of_args(T _) {
return false;
}
template<typename T, typename U, typename... Vs>
bool even_number_of_args(T _, U __, Vs... vs) {
return even_number_of_args(vs...);
}
int main() {
std::cout << even_number_of_args() << std::endl; // true
std::cout << even_number_of_args(1) << std::endl; // false
std::cout << even_number_of_args(1, "two") << std::endl; // true
std::cout << even_number_of_args(1, "two", 3.0) << std::endl; // false
std::cout << even_number_of_args(1, "two", 3.0, '4') << std::endl; // true
}
I was wondering if it was possible to write a function template that takes, as a template argument, a number N
and returns whether the number of arguments it receives is a multiple of N
. For example, the function may look something like this:
number_of_args_divisible_by_N<1>(1, "two", 3.0, '4'); // true
number_of_args_divisible_by_N<2>(1, "two", 3.0, '4'); // true
number_of_args_divisible_by_N<3>(1, "two", 3.0, '4'); // false
number_of_args_divisible_by_N<4>(1, "two", 3.0, '4'); // true
Yes, it's as simple as
template<int N, typename... Ts>
constexpr bool number_of_args_divisible_by(Ts&&...)
{
return sizeof...(Ts) % N == 0;
}
Alternatively, you can return a more metaprogramming-friendly type:
template<int N, typename... Ts>
constexpr integral_constant<bool, sizeof...(Ts) % N == 0>
number_of_args_divisible_by(Ts&&...)
{
return {};
}
Although krzaq's solution is pretty good, I think that implementing the "magic" behind sizeof...
can serve as an interesting learning exercise.
It uses a technique that is very common to template meta-programming - a non-template function covering the base case, and a template function that reduces the problem by one step:
// Base case
int count_args() {
return 0;
}
// Reduction
template<typename T, typename... Vs>
int count_args(T _, Vs... vs) {
return 1 + count_args(vs...);
}
With this functionality in place, you can implement divisibility checker using the approach from krzaq's answer:
template<int N,typename... Vs>
bool is_arg_divisible(Vs... vs) {
return count_args(vs...) % N == 0;
}
Demo.