46 votes

Est-il possible d'écrire un modèle de fonction qui indique si le nombre d'arguments est divisible par N?

J'ai appris sur variadic templates, et avec l'aide de cet excellent blog, j'ai réussi à écrire un modèle de fonction even_number_of_args qui retourne si le nombre d'arguments qu'il reçoit est divisible par 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
}

Je me demandais si il était possible d'écrire un modèle de fonction qui prend, comme un argument de modèle, un certain nombre N et retourne si le nombre d'arguments qu'il reçoit est un multiple de N. Par exemple, la fonction peut ressembler à quelque chose comme ceci:

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

70voto

KrzaQ Points 1

Oui, c'est aussi simple que

 template<int N, typename... Ts>
constexpr bool number_of_args_divisible_by(Ts&&...)
{
    return sizeof...(Ts) % N == 0;
}
 

Vous pouvez également retourner un type plus convivial pour la métaprogrammation:

 template<int N, typename... Ts>
constexpr integral_constant<bool, sizeof...(Ts) % N == 0>
number_of_args_divisible_by(Ts&&...)
{
    return {};
}
 

27voto

dasblinkenlight Points 264350

Bien que krzaq la solution est assez bon, je pense que la mise en œuvre de la "magie" derrière sizeof... peut servir comme un intéressant exercice d'apprentissage.

Il utilise une technique très commune à un modèle de méta-programmation - un non-fonction de modèle couvrant le cas de base, et un modèle de fonction qui permet de réduire le problème en une seule étape:

// Base case
int count_args() {
    return 0;
}
// Reduction
template<typename T, typename... Vs>
int count_args(T _, Vs... vs) {
    return 1 + count_args(vs...);
}

Avec cette fonctionnalité, vous pouvez mettre en œuvre la divisibilité vérificateur à l'aide de l'approche de krzaq de réponse:

template<int N,typename... Vs>
bool is_arg_divisible(Vs... vs) {
    return count_args(vs...) % N == 0;
}

La démo.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X