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

Langage C++ Discussion :

Problème de déduction de type template


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut Problème de déduction de type template
    Hello,

    J'ai un souci avec le code suivant, où le compilateur n'arrive pas à déduire le type 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
    #include <iostream>
    #include <vector>
    #include <type_traits>
     
    namespace data
    {
    	struct Foo {};
     
    	template <typename T>
    	void func(const std::vector<typename std::enable_if<std::is_pod<T>::value, T>::type>& contents)
    	{
    		std::cout << "Blah" << std::endl;
    	}
    }
     
    int main()
    {
    	std::vector<data::Foo> vec;
    	func(vec);
    	return 0;
    }
    Vous pouvez le retrouver sur ideone.com.

    Merci pour votre aide, et pour la discussion probablement intéressante que nous allons initier.

  2. #2
    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
    le compilateur ne peut déduire que les types "finaux".
    dans typename enable_if<Bidule, T>::type, le type final est ::type, qui n'est pas forcément T, il peut y avoir une spécialisation.

    A la louche, le compilateur ne peut pas déduire un type qui a besoin de typename.
    C'est d'ailleurs parce que le compilateur aura du mal à travailler avec cette chose qu'on doit lui préciser que c'est un type.

    Mais ton enable_if en type retour de la fonction, et ca ira mieux. (note, le ::type par défaut de enable_if est void, ca tombe bien)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    template <typename T>
    typename std::enable_if<std::is_pod<T>::value>::type
    func(const std::vector<T>& contents)

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Je ne peux pas.

    J'ai fait un exemple simplifié pour le forum, mais en fait, la fonction est l'opérateur de flux operator<< :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template<typename T>
    inline std::ostream& operator<<(std::ostream& out, const std::vector<typename std::enable_if<!std::is_pod<T>::value, T>::type>& contents)
    {
    	out.put(sizeof(T));
    	size_t size = contents.size();
    	out.write(reinterpret_cast<const char*>(&size), sizeof(size_t));
     
    	for (const auto& spi : contents)
    	    out << spi;
     
    	return out;
    }
    Tu noteras que cette fonction doit être appelée quand le type n'est pas un POD (contrairement au premier exemple fourni).
    Quand j'ai un POD, je serialise ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template<typename T>
    inline std::ostream& operator<<(std::ostream& out, const std::vector<T>& contents)
    {
        out.put(sizeof(T));
        size_t size = contents.size();
        out.write(reinterpret_cast<const char*>(&size), sizeof(size_t));
        out.write(reinterpret_cast<const char*>(contents.data()), contents.size()*sizeof(T));
        return out;
    }
    Dans le cas contraire, il faut être plus fin...

  4. #4
    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
    Et ceci ne fonctionnerait pas?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template<typename T>
    inline
    typename std::enable_if<!std::is_pod<T>::value, std::ostream&>::type
    operator<<(std::ostream& out, const std::vector<T>& contents) { //code si non pod }
     
    template<typename T>
    inline
    typename std::enable_if<std::is_pod<T>::value, std::ostream&>::type
    operator<<(std::ostream& out, const std::vector<T>& contents) { //code si pod }

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    operator<< est supposé renvoyer std::ostream&, afin de pouvoir chaîner les appels.

  6. #6
    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
    Oui, c'est le principe de même enable_if: bloquer les instanciations qui ne respècte pas une condition. Son usage est de remplacer un type dans la définition d'une fonction (ou d'une classe)

    enable_if<cond, T>::type est T si cond est vrai, non défini sinon.

    Donc typename enable_if< std::is_pod<T>::value, std::ostream&>::type est std::ostream& si T est is_pod, et ne compile pas sinon
    Grace à SFINAE, cette impossibilité de définir la template pour ce T précis n'est pas une erreur, si une autre template compile correctement.

    Les deux templates de fonctions de mon message précédents définissent deux templates de surcharges de <<. Elles retournent toutes deux des std::ostream& car c'est le type "résultat" du enable_if.


    enable_if se comporte comme suis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<bool B, class T = void>
    struct enable_if {};
     
    template<class T>
    struct enable_if<true, T> { using type = T; };

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 12
    Dernier message: 02/12/2010, 11h36
  2. Réponses: 2
    Dernier message: 17/10/2010, 15h11
  3. [phpBB] Function avec le Template phpBB
    Par mangafan dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 5
    Dernier message: 27/09/2005, 16h32
  4. Problème de requete avec type monétaire
    Par Pymm dans le forum ASP
    Réponses: 11
    Dernier message: 09/09/2005, 16h57
  5. Problème de champs Paradox type : mémo formaté
    Par mjp dans le forum Bases de données
    Réponses: 6
    Dernier message: 05/04/2005, 21h13

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