IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

spécialisation de trait et template membre de template


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut spécialisation de trait et template membre de template
    Salut à vous!

    Je souhaite surcharger un trait pour une template de structure (Item) membre d'une autre template de structure (System).
    Bien entendu, je n'y arrive pas.
    Mon compilateur est Visual C++ 2019 en 16.9.6.

    Voici le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    template <typename... Ts>
    // requires Ts.. tous distincts
    struct System {
        template <typename T>
        // requires T est dans Ts
        struct Item {
          static constexpr std::size_t index = 0;// en vrai, c'est index_in_types<T, Ts...>, mais pour l'exemple, ca suffira bien.
        };
    };
     
     
    // le trait (cas général)
    template <typename T>
    struct trait: std::false_type {};
     
    // le cas que j'essaie d'écrire
    template <typename T, typename... Ts>
    struct trait< typename System<Ts...>::template Item<T> >: std::true_type {};
    Visual se plaint pour [c]T[§c] et Ts....
    Citation Envoyé par Visual C++
    error C2764: T : paramètre de modèle non utilisé ou pouvant être déduit dans la spécialisation partielle 'trait< typename System<Ts...>::template Item<T> >'
    Soit je suis bigleuse, soit il y a quelque chose d'étrange dont j'ai pas conscience.


    Et si j'introduis un alias, j'obtiens le même résultat.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename T, typename... Ts>
    using alias = typename System<Ts...>::template Item<T>;
     
    template <typename T, typename... Ts>
    struct trait< alias <T, Ts...> >: std::true_type {};
    L'idée sous-jacente est de pouvoir écrire un concept qui accepte les Item et quelques types construits avec (technique du template expression)

    Comment puis-je m'en sortir?

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Ton trait<> s'attend à recevoir un type, et à partir de ce type il devrait pouvoir lui associer l'expression typename System<Ts...>::template Item<T>, ça revient à lui demander de chercher tous les Ts et le T de cette expression pour vérifier que c'est bien un Item<T>.

    La seule chose qu'il peut résoudre c'est extrêmement simple, par exemple si T est un pointeur, il peut lui associer U* et trouver le type pointé.
    Il faut fournir tous les éléments nécessaires, par exemple tous les Ts et le T:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    #include <iostream>
    #include <concepts>
    #include <type_traits>
     
    template <class T, class... Ts>
     struct any_same : std::disjunction<std::is_same<T,Ts>...> {};
     
    template<typename T,typename First,typename...Ts>
     constexpr size_t  elmt_index()noexcept {
    	if constexpr ( std::is_same_v<T,First> ) {
    		return  0;
    	}
    	else if constexpr ( sizeof...(Ts) == 0 ) {
    		static_assert( sizeof(T)==0 , "T n'est pas dans la liste des Ts" );
    	}
    	else {
    		//static_assert( sizeof...(Ts) != 0 );
    		return  1 + elmt_index<T,Ts...>();
    	}
    }
     
    template<class... Ts> requires std::negation_v<any_same<Ts...>>
     struct System {
    	template<typename T> requires any_same<T,Ts...>::value
    	struct Item {
    		static constexpr std::size_t index = elmt_index<T,Ts...>();
    	};
    };
     
    template<typename T,typename...Ts>
     struct trait : std::false_type {};
    template<typename T,typename...Ts>
     requires requires { typename System<Ts...>::template Item<T>; } // cas où Item<T> existe dans System<Ts...>
     struct trait<T,Ts...> : std::true_type {};
     
    int  main() {
    	System<int, float,char>::Item<float>  x;
    	//System<float, float> y;
    	//System<int,float,char>::Item<double>  z;
    	//size_t w = elmt_index<double, int>();
     
    	static_assert( trait<float, int,float,char>::value );
    	static_assert( ! trait<double, int,float,char>::value );
    }
    Mais si ton but est d'à partir d'un type TT, est juste de vérifier c'est bien un System<???>::Item<TT>, il suffit de mettre dans Item<TT>: using ElementDeSystem = std::tuple<Ts...>;, et tu peux retrouver si c'est le cas et même retrouver ses paramètres.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template<typename>
     struct trait2 : std::false_type {};
    template<typename T>
     requires requires { typename T::ElementDeSystem; }
     struct trait2<T> : std::true_type {
        using Elements = T::ElementDeSystem;
    };

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Merci, je vais voir ce que ca donne.

Discussions similaires

  1. Réponses: 3
    Dernier message: 13/10/2012, 15h02
  2. Réponses: 6
    Dernier message: 17/07/2012, 10h20
  3. Réponses: 9
    Dernier message: 24/03/2011, 21h54
  4. [Template] Spécialisation partielle d'un template
    Par Kurisu dans le forum Langage
    Réponses: 31
    Dernier message: 25/11/2008, 22h21
  5. Réponses: 19
    Dernier message: 18/03/2007, 16h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo