39 votes

Comment puis-je vérifier que le type T fait partie du paquet de paramètres Ts... ?

Je veux écrire une fonction pour retourner vrai si T est l'un des Ts...

template<class T, class... Ts>
bool is_one_of<T, Ts...>();

Par exemple, is_one_of<int, double, int, float> rendements true, et is_one_of<int, double, std::string, bool, bool> rendements false.

Ma propre mise en œuvre est

template<class T1, class T2>
bool is_one_of<T1, T2>() {
    return std::is_same<T1, T2>;
}

template<class T1, class T2, class... Ts>
bool is_one_of<T1, T2, Ts...>() {
    if (std::is_same<T1, T2>) {
        return true;
    }
    else {
        return is_one_of<T1, Ts...>();
    }
}

Cette vérification me semble commune, alors je me demande s'il existe déjà une telle fonction dans la bibliothèque standard.

41voto

Shaoyu Chen Points 386

Dans votre propre implémentation, un problème est que C++ ne permet pas la spécialisation partielle sur les modèles de fonction.

Vous pouvez utiliser l'expression fold (qui est introduite en C++17) au lieu de l'appel de fonction récursif.

template<class T1, class... Ts>
constexpr bool is_one_of() noexcept {
    return (std::is_same_v<T1, Ts> || ...);
}

Si vous utilisez C++11 où l'expression fold et std::disjunction ne sont pas disponibles, vous pouvez implémenter is_one_of comme ceci :

template<class...> struct is_one_of: std::false_type {};
template<class T1, class T2> struct is_one_of<T1, T2>: std::is_same<T1, T2> {};
template<class T1, class T2, class... Ts> struct is_one_of<T1, T2, Ts...>: std::conditional<std::is_same<T1, T2>::value, std::is_same<T1, T2>, is_one_of<T1, Ts...>>::type {};

32voto

L. F. Points 11270

Vous pouvez également utiliser std::disjunction pour éviter l'instanciation inutile du modèle :

template <class T0, class... Ts>
constexpr bool is_one_of = std::disjunction_v<std::is_same<T0, Ts>...>;

Une fois qu'un type correspondant est trouvé, les modèles restants ne sont pas instanciés. En revanche, une expression de pliage les instancie tous. Cela peut faire une différence significative dans le temps de compilation en fonction de votre cas d'utilisation.

10voto

Yakk Points 31636

Vérifiez si le type T fait partie du paquet de paramètres Ts :

template<class T0, class... Ts>
constexpr bool is_one_of = (std::is_same<T0, Ts>{}||...);

variable de modèle.

Alternative :

template<class T0, class... Ts>
constexpr std::integral_constant<bool,(std::is_same<T0, Ts>{}||...)> is_one_of = {};

Qui a des différences subtiles.

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