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 :

[C++0x] Ressuscitons les concepts avec « SFINAE for expressions »


Sujet :

Langage C++

  1. #1
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut [C++0x] Ressuscitons les concepts avec « SFINAE for expressions »
    Bonjour à tous,

    Je fais suite à cette conversation dans la rubrique « Langage » étant donné que ça n'a plus rien à voir avec Boost.

    Pour résumer :
    Il existe la bibliothèque boost::concept_check qui permet de formaliser des concepts à partir d'un ensemble d'expressions. C'est pratique (pour avoir des messages d'erreurs plus explicites) et très expressif, mais ça ne permet pas de faire de surcharge. Il y a donc une grosse perte d'intérêt par rapport aux concepts initiaux de C++0x qui, je le rappelle, ont été abandonnés.

    Il y a cependant un espoir : il sera possible (et même est possible avec GCC 4.4 et peut-être d'autres compilateurs récents) d'exploiter le mécanisme SFINAE pour les expressions. Il faut bien sûr que l'expression apparaisse dans la signature de la fonction à surcharger ; pour ce faire on utilise decltype, également nouvelle fonctionnalité de C++0x.

    Rien de plus clair qu'un petit exemple.
    On a une classe X et un classe Y.
    Il est possible de multiplier des X entre eux, mais pas des Y.
    Il est possible d'additionner des Y entre eux, mais pas des X.
    On souhaite surcharger le template de fonction f :
    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    #include <iostream>
     
    struct X
    {
    	X(int value):
    		value_(value)
    	{
    	}
     
    	int value_;
    };
     
    X
    operator*(X x1, X x2)
    {
    	return X(x1.value_ * x2.value_);
    }
     
     
     
    struct Y
    {
    	Y(int value):
    		value_(value)
    	{
    	}
     
    	int value_;
    };
     
    Y
    operator+(Y y1, Y y2)
    {
    	return Y(y1.value_ + y2.value_);
    }
     
     
     
    template<class T>
    auto
    f(T t1, T t2) -> decltype(t1 + t2) // #1
    {
    	std::cout << "#1\n";
    	return t1 + t2;
    }
     
    template<class T>
    auto
    f(T t1, T t2) -> decltype(t1 * t2) // #2
    {
    	std::cout << "#2\n";
    	return t1 * t2;
    }
     
    int main()
    {
    	X x1(0), x2(0);
    	X x3 = f(x1, x2); // deduction fails on #1 (cannot add X+X), calls #2
     
    	Y y1(0), y2(0);
    	Y y3 = f(y1, y2); // calls #1
    }

    Il est tout à fait possible d'utiliser le mécanisme avec des signatures de fonction classiques (c'est-à-dire n'ayant pas la forme « auto f() -> decltype »), en utilisant par exemple un « paramètre fantôme » (comme on peut le faire avec boost::enable_if) :
    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
     
    template<typename>
    class require
    {
    	public:
    		typedef void* type;
    };
     
    //#1
    template<class T>
    T
    f(T t1, T t2, typename require<decltype(t1 * t2)>::type = 0)
    {
    	std::cout << "#1\n";
    	return t1 * t2;
    }
     
    //#2
    template<class T>
    T
    f(T t1, T t2, typename require<decltype(t1 + t2)>::type = 0)
    {
    	std::cout << "#2\n";
    	return t1 + t2;
    }
     
    int main()
    {
    	X x1(0), x2(0);
    	Y y1(0), y2(0);
     
    	X x3 = f(x1, x2); //calls #1
    	Y y3 = f(y1, y2); //calls #2
    }

    Pensez-vous qu'à partir de cette piste, il soit possible d'externaliser les expressions et de les regrouper dans une même classe qui serait alors une classe « concept » (de la même façon qu'avec boost::concept_check, pour ceux qui connaissent) ?

    Au fond de moi je me dis « si c'était possible, ça se saurait, un gourou en aurait déjà parlé au moment du tollé lors de l'abandon des concepts », mais je tente tout de même le coup .
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  2. #2
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Un template qui utiliserait un peu le même style que les typelists "fonctionnelle" pour pouvoir chainer des requirements, ce qui au final caserait toutes les expressions dans un même type ?

    Un truc qui prend une expression et met à la suite/au début son decltype dans la typelist ?

    Une macro qui permettrait ainsi de rajouter un decltype(e) à une typelist ? Enfin, les macros standard de loki.

  3. #3
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Ah oui…
    Un typedef d'instanciation de template variadique, quoi ?

    C'est une bonne idée, mais c'est quand même moins pratique qu'une série d'instructions à la boost::concept_check…
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  4. #4
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Citation Envoyé par Florian Goo Voir le message
    Ah oui…
    Un typedef d'instanciation de template variadique, quoi ?

    C'est une bonne idée, mais c'est quand même moins pratique qu'une série d'instructions à la boost::concept_check…
    Bah dans une macro tu prends les expressions, t'appliques un decltype à chacune, et chacune part en paramètre d'un même template, et c'est ce dernier qui régira sélection de la surcharge.

  5. #5
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Oui oui j'avais saisi .

    Je disais juste que c'était moins pratique par rapport à concept_check.

    Par exemple, on est obligé d'imposer des requirements sur la façon dont peuvent être construits les objets (vu qu'on est obligé de les instancier dans les decltype), ce qui est une problématique résolue par concept_check de cette façon : http://www.boost.org/doc/libs/1_41_0...g_concepts.htm (voir paragraphe « Values for Usage Patterns Should Be Data Members »).

    Autre chose, si on veut écrire plusieurs instructions de suite pour exprimer un seul requirement, je ne sais pas comment contourner ça…

    Mais je pense que c'est une piste intéressante !
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  6. #6
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    L'avantage est toutefois que c'est moins verbeux et qu'au final on perd le côté "interface de POO" (nominal) des concepts pour laisser profit au côté structurel, "à la templates", c'est à dire qu'on va se baser sur l'expression pour autoriser ou non, plutôt que sur un nom associé (idem que templates vs interfaces).

  7. #7
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Je viens de tomber par hasard sur quelque chose de potentiellement intéressant. Une tentative d'émulation des concepts avec « decltype » et « SFINAE for expressions » : http://pizer.wordpress.com/2009/08/1...ncepts-no-fun/
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

Discussions similaires

  1. Conception avec les threads et les sockets
    Par tir0nik dans le forum Développement
    Réponses: 0
    Dernier message: 19/07/2009, 18h28
  2. conception avec les procédure stockées
    Par ammouna24 dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 18/06/2009, 23h27
  3. Réponses: 5
    Dernier message: 04/03/2007, 15h33
  4. Lister les dossiers avec un for
    Par AnkyFive dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 25/09/2006, 10h14
  5. [ASE] Les locks avec un cursor for update
    Par PiyuXYZ dans le forum Sybase
    Réponses: 1
    Dernier message: 11/02/2006, 13h17

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