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

Boost C++ Discussion :

concept_check et SFINAE


Sujet :

Boost C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut concept_check et SFINAE (edit : et C++0x aussi)
    Salut à tous,

    Je fais peu à peu mon deuil de la non inclusion des concepts dans C++0x en me penchant sur boost::concept_check, qui a finalement l'air intéressant.

    Peut-on surcharger une fonction en utilisant concept_check et le mécanisme SFINAE ?
    J'ai pensé que la simple utilisation de concept_check permettait ça (car tout est inclus dans la signature de la fonction), mais il semblerait que non :
    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
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
     
    #include <iostream>
    #include <boost/concept_check.hpp>
    #include <boost/concept/requires.hpp>
     
    class integer
    {
    	public:
    		integer(int value):
    			value_(value)
    		{
    		}
     
    		int
    		value() const
    		{
    			return value_;
    		}
     
    	private:
    		int value_;
    };
     
    bool
    operator==(const integer& i, const integer& j)
    {
    	return i.value() == j.value();
    }
     
    template<typename T>
    class Comparable
    {
    	public:
    		BOOST_CONCEPT_USAGE(Comparable)
    		{
    			t1 == t2;
    		}
     
    	private:
    		T t1;
    		T t2;
    };
     
    template<typename T>
    class JavaStyleComparable
    {
    	public:
    		BOOST_CONCEPT_USAGE(JavaStyleComparable)
    		{
    			t1.equals(t2);
    		}
     
    	private:
    		T t1;
    		T t2;
    };
     
    template<typename T>
    BOOST_CONCEPT_REQUIRES
    (
    	((Comparable<T>)),
    	(bool)
    )
    same_value(const T& t1, const T& t2)
    {
    	return t1 == t2;
    }
     
    template<typename T>
    BOOST_CONCEPT_REQUIRES
    (
    	((JavaStyleComparable<T>)),
    	(bool)
    )
    same_value(const T& t1, const T& t2)
    {
    	return t1.equals(t2);
    }
     
    int
    main()
    {
    	integer i(0);
    	integer j(0);
     
    	if(same_value(i, j))
    	{
    		std::cout << "woohoo!\n";
    	}
    	else
    	{
    		std::cout << "d'oh!\n";
    	}
     
    	return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    main.cpp|85| error: call of overloaded ‘same_value(integer&, integer&)’ is ambiguous
    main.cpp|63| note: candidates are: typename boost::Requires_<(0 + boost::_requires_::value), void (*)(bool)>::type same_value(const T&, const T&) [with T = integer]
    main.cpp|74| note:                 typename boost::Requires_<(0 + boost::_requires_::value), void (*)(bool)>::type same_value(const T&, const T&) [with T = integer]
    || main.cpp: In destructor ‘JavaStyleComparable<T>::~JavaStyleComparable() [with T = integer]’:
    /usr/include/boost/concept/detail/general.hpp|29| instantiated from ‘static void boost::concept::requirement<Model>::failed() [with Model = JavaStyleComparable<integer>]’
    /usr/include/boost/concept/requires.hpp|31| instantiated from ‘boost::_requires_<void (*)(JavaStyleComparable<integer>)>’
    main.cpp|85| instantiated from here
    main.cpp|49| error: ‘class integer’ has no member named ‘equals’
    J'ai parcouru la doc et je n'ai pas vu un tel cas d'utilisation. On peut faire quelque chose en ajoutant du enable_if ? Si oui comment ?
    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
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Bon. Déjà le couple concept_check/enable_if, c'est mouru :
    Citation Envoyé par Dave Abrahams
    on Wed Jan 30 2008, Johan Torp <johan.torp-AT-gmail.com> wrote:

    > Is there any way to combine boost::enable_if and the concept check library?
    > For instance to disable a function overload for template parameters which
    > doesn't model some STL concept.

    Nope. Those concepts perform checks that cause hard compile-time
    errors. Once they've failed, it's too late to recover... and not all
    concept check failures can be converted to non-error true/false results
    in C++03.
    http://lists.boost.org/Archives/boos.../01/132842.php


    Et pour SFINAE tout court, j'en ai aussi bien l'impression.
    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.

  3. #3
    Membre très actif
    Profil pro
    professeur des universités à la retraite
    Inscrit en
    Août 2008
    Messages
    364
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : professeur des universités à la retraite

    Informations forums :
    Inscription : Août 2008
    Messages : 364
    Par défaut
    Que veux-tu dire en ce qui concerne SFINAE ? C'est une technique de programmation comment ça pourrait "mouruir" ?

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Pardonne-moi mais je n'ai pas compris ta question ?
    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.

  5. #5
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Citation Envoyé par ptyxs Voir le message
    Que veux-tu dire en ce qui concerne SFINAE ? C'est une technique de programmation comment ça pourrait "mouruir" ?

    Il parlait de l'utilisation conjointe de boost::enable_if et concept_check. C'est "mourru" dans le sens c'est pas possible .

    Quand a flo : euh non là sur le coup jvois pas :s.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    J'ai causé un peu avec Alp et il m'a parlé de ça :
    http://www.open-std.org/jtc1/sc22/wg...008/n2634.html
    Du SFINAE pour les expressions.

    Vu que le principe de concept_check (et en particulier de BOOST_CONCEPT_REQUIRES) est d'imposer une série d'instruction dans la signature de la fonction, ça m'a l'air d'être la bonne feature pour permettre une surcharge de fonctions comme je le souhaite et comme les concepts de C++0x le promettaient.
    D'ailleurs loufoque en causait furtivement ici, mais ça m'est passé sous le nez : http://www.developpez.net/forums/d77...s/#post4520427

    Y'a bon.
    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.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Euh non attendez, pas du tout…
    http://gcc.gnu.org/projects/cxx0x.html
    GCC 4.4, qui est le compilo que j'utilise, implémente déjà la fonctionnalité « Solving the SFINAE problem for expressions ».

    J'ai activé C++0x et l'erreur est toujours présente.


    En me basant sur l'exemple donné dans le proposal, j'écris un code complet pour tester :
    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
    #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
    }
    Non seulement ça compile, mais en plus j'ai bien la sortie attendue :
    Donc ça fonctionne bien.

    On est obligé d'utiliser decltype, donc ?
    Et si on veut surcharger une fonction qui renvoie void, on fait comment ?
    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.

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

Discussions similaires

  1. SFINAE. (je ne comprend pas)
    Par Invité dans le forum Langage
    Réponses: 8
    Dernier message: 19/08/2014, 11h04
  2. Visibilité de template et SFINAE
    Par vikki dans le forum Langage
    Réponses: 8
    Dernier message: 06/07/2011, 13h54
  3. Réponses: 6
    Dernier message: 04/01/2010, 02h35

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