0
votes

Comment simplifier l'alias d'activation_if dans le paramètre Modèle de modèle

Mon objectif est d'avoir une struct qui prend un alias à un spécialisé enable_if_t code> avec un paquet de paramètres Varididic de typename et me dit ensuite si le activer_if code> ' s Conditions étaient satisfaites pour tous les types dans le pack. J'ai un tas de ces activisisés_if code> s, mais devez écrire des tests pour eux avant de pouvoir les mettre dans notre projet Open Source. J'ai environ 2000+ lignes de code testant manuellement ces spécialisations, mais je parie que je peux l'obtenir à 100 ou 200 si je peux comprendre le modèle ci-dessous. J'ai une version de travail (+ Godbolt Link), mais TBH Je ne sais pas pourquoi cela fonctionne et que ce régime est en train de casser dans un cas où la mise en œuvre reçoit un pack de paramètres

Voici un exemple du code que je voudrais écrire et c'est le résultat. J'utilise C ++ 14 et peut voler des implémentations de base des objets à partir de C ++ 17 aime la conjonction et Void_T p> xxx pré>

Le ci-dessous fait ce que je veux, mais tbf i Je ne comprends pas vraiment comment. P>

// Enable if for checking if all types are arithmetic 
template <typename... Types>
using require_all_arithmetic = std::enable_if_t<conjunction<std::is_arithmetic<Types>...>::value>;
/// For the tests

TEST(requires, arithmetic_all_test) {
  EXPECT_FALSE((require_variadic_tester<require_all_arithmetic, std::string,
     Eigen::Matrix<float, -1, -1>>::value));
  EXPECT_TRUE((require_variadic_tester<require_all_arithmetic,
     double, int, float>::value));
}


2 commentaires

Pour répondre à votre première question: si check est mal formé, puis requier_tester_impl sera une dérivation de faux_type Étant donné que la substitution des modèles échoue pendant la spécialisation, la réalisation de la mise en œuvre non spécialisée, alors que si elle est bien formée, elle sera spécialisée avec succès en tant que dérivation de true_type .


Merci! Je pense que ce que je ne comprends pas spécifiquement, c'est pourquoi check étant mal formé ne provoque pas que Sfinae s'en va et utilise la spécialisation non partielle.


3 Réponses :


0
votes
template<template<class...> class Check, class... Ts>
using require_variadic_tester = 
   std::conditional_t<require_variadic_tester_impl<Check, Ts...>(42),
                      std::true_type, std::false_type>;


5 commentaires

Merci d'avoir répondu! J'ai besoin de la conjonction à l'intérieur de l'enable_if. J'ai mis à jour la question initiale avec plus de contexte


@Steve_corrin édité.


Wow! J'apprécie la réponse! Aussi mes excuses, le commentaire que j'ai mentionné ci-dessus était pour une autre réponse, mais rafraîchissant le post m'a fait jumblée. Votre méthode proposée est v nice, j'essaie de faire venir notre équipe pour aller jusqu'à C ++ 17 et voir un peu d'arrosage de consexpr étant cool peut aider à les convaincre un peu!


@Steve_corrin consexpr peut être utilisé dans C ++ 14 (et c ++ 11 aussi). J'ai compilé les exemples avec C ++ 17 pour std :: conditionnel , c'est tout. Tout le reste doit être valide avec un compilateur complet en vedette C ++ 14 .


Oh, je pensais que Constexpr était une utilisation limitée en C ++ 14 (uniquement dans les définitions de la fonction). J'ai l'impression que je leur ai essayé il y a quelque temps et que notre Windows construisait était vraisement malheureux. Je vais jouer avec ça!



0
votes

Je ne sais pas de comprendre tous vos besoins, mais ...

Ce que je voudrais obtenir est un exiger_varididic_tester qui prend dans un alias modélisé variadique, quelque chose comme activer_if > :: valeur> < / code>, et me donne vrai ou faux. Malheureusement, le renvoie ci-dessous faux, peu importe quels types sont entrés dans

Êtes-vous sûr de vouloir conjonction > ?

ou voulez-vous conjonction ...> ?

Je veux dire ... Le chèque doit recevoir une liste de types variadiques ou souhaitez-vous vérifier un alias, que (comme dans votre exemple) reçoit un type unique et une conjonction qui est true iff (si et seulement si) la vérification est satisfaite pour tous les types?

Dans ce second cas, std :: void_t est très pratique pour Vérifiez que tous les chèques sont satisfaits.

Je propose le suivant requir_varididic_impl et require_variiadic_tester xxx

Maintenant de xxx

vous obtenez xxx

pense que mon défaut de comprendre void_t dans la première fonction méta est causant mon malentendu

Essayez de penser std :: Void_T comme "Activer si tout TS est activé".


3 commentaires

Merci d'avoir répondu! Le Void_T a plus de sens maintenant. Bien que j'ai besoin de la conjonction à l'intérieur de l'enable_if. J'ai mis à jour la question initiale avec plus de contexte


@Steve_corrin - Il me semble que vous avez besoin de Modèle Utilisation requis_all_arithmetic = STD :: Void_T > ...> . La "conjonction à l'intérieur" est std :: void_t .


Je voudrais laisser le vide_t à l'extérieur de l'exigence_all_arithmétique car il n'est pas nécessaire lorsque nécessaire_ * s sont utilisés dans les modèles de fonctions



1
votes

Voici ce qui se passe avec votre nécessitent_tester :

Ceci ne correspond pas à la spécialisation partielle de requier_tester , qui a juste Arguments de deux modèles , nous utilisons donc le modèle principal xxx

avec check = require_arithmetic ; t = double ; Types = Double, Int . Il ne correspond pas à la spécialisation partielle de requiert_tester . Membre valeur est le résultat de xxx

où la pièce intéressante est requier_tester_impl = requis_tester_impl < / code>. Premièrement, puisque les paramètres de modèle de requir_tester_impl sont xxx

et seulement deux arguments de modèle explicite sont donnés, nous savons que les arguments de modèle réels sont . Maintenant, nous devons voir si cela correspond ou non à la spécialisation partielle de requier_template_impl , nous essayons donc de correspondre à: xxx

SO Template Argument déduction Déduction < Code> Check = Exiger_arithmetic et t1 = double . Le type void_t > ne provoque aucune déduction de vérifier ou t1 . Mais les valeurs de paramètres déduites doivent être remplacées dans, et nous trouvons void_t > est void_t > est annulation . Ceci correspond à la Void à partir des arguments de modèle, de sorte que la spécialisation partielle correspond à la correspondance, et requier_template_impl hériter std :: true_type , pas std :: faux_type .

d'autre part, si t1 était std :: string de double , substituer les arguments de modèle déduits dans Wider (code> void_t > est invalide, via l'éventuel activer_if << / code> ... > :: Type Si aucun membre type existe. Lors de la substitution des arguments de modèle déduits dans d'autres paramètres de modèle échouent, cela signifie que la spécialisation partielle est jetée comme non une correspondance. SO nécessitent_template_impl utilise le modèle principal et hérités std :: faux_type .

retour au Valeur Membre de Exiger_Tester , il trouve Récursivement (code> requis_tester :: valeur via EXCEX_TESTER :: Valeur via requier_tester :: valeur identique à requier_tester :: valeur . Toutes les membres sont tristes, de sorte que la valeur finale est vraie.

Bien que je simplifie cela un peu:

  1. Le vide est inutile dans la récursion requis_tester et provoque l'étrange "fait" que requier_tester :: valeur < / code> est toujours vrai. Il serait préférable de supprimer le = vide par défaut à partir du modèle principal EXCEPTE_TESTER et faites le boîtier de base Modèle Vérification de la classe> Exiger_Tester à la place.

  2. Votre expression dans l'expression requier_tester donne toujours exactement deux arguments de modèle à conjonction , donc ce n'est pas vraiment en train d'utiliser Sa propriété variadique, et vous pouvez aussi bien écrire exiger_tester_impl << / code> ... > :: valeur && requri_tester << / code> ... > :: Valeur . Étant donné que exiger_tester fait une récursion elle-même, elle n'a pas besoin de la définition récursive abstraite dans conjonction . Au lieu de cela, requir_tester pourrait être simplifié pour compter sur conjonction et éviter de faire une récursion elle-même: XXX

    Le modèle requir_varididic_tester peut suivre un motif similaire, sauf que je vais donner le paramètre Modèle mannequin qui n'était que typename = vide un nom, < Code> Typename Activer . Et il doit arriver avant le jeu de paramètres de modèle, il n'est donc pas utile de la défaut de défaut à Void , et nous devons veiller à utiliser l'argument de modèle approprié Dans la position correspondante. xxx

    voir Le programme modifié sur Godbolt , avec les résultats souhaités.


1 commentaires

Cette réponse est magnifique, élégante, osez-moi dire même sexy. Merci beaucoup pour l'explication et le code !!