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 classes et valeurs de retour


Sujet :

C++

  1. #1
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut Spécialisation de classes et valeurs de retour
    Bonjour,

    j'ai un petit souci avec certaines fonctions membres d'une classe spécialisée. J'ai défini une classe Vector pour manipuler des vecteurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template<template<typename T>class storage,typename precision> Vector : storage<precision>
    {};
    Cette fonction admet pour paramètre une structure "storage" précisant le format de stockage de ses coefficients et une "precision" (int, float, double, ...). Pour le stockage, j'ai par exemple une structure dense :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename precision> struct dense
    {
        size_t size_;
        precision* val_;
    };
    En fonction du format de stockage, je n'ai pas exactement les mêmes fonctions membres pour la classe Vector et je procède par spécialisation pour contourner ce problème. Dans le cas dense, j'ai :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<typename precision> class Vector<dense,precision> : dense<precision>
    {
    public:
        Vector(Vector<dense,precision> const&);
    public:
        precision const sum() const;
        Vector<dense,precision> abs() const;
    };
    Dans cet exemple, le constructeur par copie et la fonction sum compilent bien mais pas la fonction abs. Le compilateur me jette en me disant qu'il a un problème avec la structure dense qui n'est pas conforme avec la façon dont est défini le paramètre storage dans la déclaration générale de Vector (la toute première). Seulement, je ne comprends pas pourquoi et je n'arrive pas à corriger le problème.

    Est-ce que quelqu'un aurait une idée?

    Merci pour votre aide.

  2. #2
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Tu aurais un code pour reproduire l'erreur ? Avec les informations actuelles ca compile très bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    template<class> struct dense;
     
    template<template<class> class, class>
    class Vector;
     
    template<class precision>
    class Vector<dense,precision> : dense<precision>
    {
      public:
        Vector<dense,precision> foo();
    };
    (Seul le point de vue syntaxe est vérifié par le compilo, il peut y avoir d'autre erreur lié à l'instanciation, mais il faut plus de code pour ca).

    NB: Tu peux marquer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Vector foo();
    //a la place de
    Vector<dense,precision> foo();

  3. #3
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Merci pour ta réponse Flob90.
    Je viens de vérifier et apparemment Visual Studio 2010 refuse cette syntaxe. En revanche, avec la syntaxe que tu suggères en nota bene, ça compile nickel :
    Merci bien je passe en résolu!

  4. #4
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonjour,

    désolé de revenir sur cette question mais j'ai finalement toujours le même problème, même s'il se pose un peu différemment. Voici le bout de code qui pose problème chez moi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    template<template<typename T> class stockage,typename precision> class Vecteur : stockage<precision> {};
     
    template<typename precision> class Vecteur<dense,precision> : dense<precision>
    {
    	Vecteur fun1(); // compile
    	Vecteur<dense,precision> fun2(); // ne compile pas
    	Vecteur<dense,int> fun3(); // ne compile pas
    };
     
    int main()
    {
    	Vecteur<dense,double> toto;
    	return 0;
    }
    Bien que fun2 ne compile pas, cela ne m'a finalement pas posé de problème puisque j'obtiens la compilation avec fun1, c'est-à-dire en ne précisant pas les paramètres template du Vecteur retourné (cf réponse de Flob90). J'en ai déduit que c'était juste un problème de syntaxe. Sauf que maintenant, j'ai besoin de déclarer une fonction fun3 qui renvoie un Vecteur<dense,int> et je me retrouve confronté au même problème que celui de départ, à savoir que ça ne compile pas.

    Qu'est-ce que je fais mal?

    Merci bien pour vos réponses!

    PS : je confirme que le code tel qu'il est donné ne compile pas. Si ça compile chez vous, c'est qu'il y a un problème avec mon compilo (Visual 2010).

    EDIT : erreur obtenue sous Visual 2010 : error C3200: 'dense<precision>'*: argument template non valide pour le paramètre de modèle 'stockage', modèle de classe attendu

    et voici le lien vers l'erreur : http://msdn.microsoft.com/en-us/library/3xwxftta.aspx qui affirme que je n'ai pas le droit de faire ce que je fais mais je me demande si c'est du made-in-microsoft ou si je ne respecte vraiment pas le langage. Dans le dernier cas, existe-t-il une solution de contournement autre que spécialiser ma classe pour toutes les précisions (horrible!)?

  5. #5
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Je viens de trouver la solution : il faut supprimer les extensions de langage qui sont mises par défaut dans Visual (option /Za). Ca compile maintenant.

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Ca sent bon la régression. Le cas proposé dans le MSDN est différent : c'est comme si tu avais mis int à la place de dense.
    Désactiver les extensions de langage : je me souviens d'un vieux conseil d'Arzar m'ayant indiqué que cela était pas recommandé par MS, l'option de compil pouvant même devenir deprecated : cf ici

    Bon, j'arrive pas à mieux que ça :
    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
    #include <iostream>
     
    template<template<typename T> class stockage,typename precision> class Vecteur : stockage<precision> {};
     
    template<class T> struct dense{};
     
    template<typename precision> class Vecteur<dense,precision>; // (1)
     
    template<typename precision> struct rebind_vecteur_dense
    {
        typedef Vecteur<dense,precision> type;
    };
     
    template<typename precision> class Vecteur<dense,precision> : dense<precision>
    {
        public:
    	Vecteur fun1()
    	{
    	    std::cout<<"1\n";
    	    return Vecteur();
    	}
       typedef typename rebind_vecteur_dense<precision>::type type1;
    	type1 fun2()
    	{
    	    std::cout<<"2\n";
    	    return type1();
    	}
       typedef typename rebind_vecteur_dense<int>::type type2;
    	type2* fun3()
    	{
           type2 t;
           t.fun1();
           t.fun2();
    	    std::cout<<"3\n";
    	    return 0;
    	}
     
     //  type2 fun4()
    	//{
     //      type2 t;
     //      t.fun1();
     //      t.fun2();
    	//    std::cout<<"3\n";
    	//    return 0;
    	//}
    };
     
    int main()
    {
    	Vecteur<dense,double> toto;
    	toto.fun1();
    	toto.fun2();
    	toto.fun3();
    	Vecteur<dense,int> toto2;
    	toto2.fun1();
    	toto2.fun2();
    	toto2.fun3();
    	return 0;
    }
    Si j'essaie un retour par valeur (fun4), alors le compilateur plante (belle boite d'anomalie ) :
    AppName: cl.exe AppVer: 16.0.30319.1 AppStamp:4ba1dc05
    ModName: c1xx.dll ModVer: 16.0.30319.1 ModStamp:4ba1dc95
    fDebug: 0 Offset: 00107763
    Ceci dit, cela demanderait de se replonger dans la norme pour le // (1) et voir ce que cela implique par rapport à la spécialisation partielle qui suit.

  7. #7
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Merci pour ta réponse 3DArchi.
    Je vais essayer de me renseigner sur ce fameux bug du compilo ou de voir comment contourner le problème sans désactiver les extensions de langage.
    J'ai quand même besoin de faire du code portable donc pour l'instant je suis bloqué.
    Je n'ai pas accès à la norme donc je vais devoir faire sans.

  8. #8
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonsoir,

    j'ai fini par trouver la syntaxe fonctionnant sans désactiver les extensions de langage dans ce forum :

    http://www.velocityreviews.com/forum...ror-c3200.html

    La syntaxe en question est
    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
    template<template<typename T> class stockage,typename precision> class Vecteur : stockage<precision> {};
     
    template<typename precision> class Vecteur<dense,precision> : dense<precision>
    {
                  // syntaxes valides si désactivation des extensions de langage
     
                  Vecteur<dense,precision> fun2(); 	
                  Vecteur<dense,int> fun3(); 
     
                  // syntaxes inconditionnellement valides
     
    	Vecteur<::dense,precision> fun2(); 
    	Vecteur<::dense,int> fun3(); 
    };
     
    int main()
    {
    	Vecteur<dense,double> toto;
    	return 0;
    }
    Si quelqu'un a une explication, je suis preneur!

    EDIT : a priori, dans les deux premières syntaxes, dense est interprété comme étant dense<precision> (cf message de Flob90), alors qu'avec l'opérateur de portée on précise bien que l'on souhaite faire référence à la structure dense (mais tout cela reste à confirmer).

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

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Citation Envoyé par Aleph69 Voir le message
    Je viens de trouver la solution : il faut supprimer les extensions de langage qui sont mises par défaut dans Visual (option /Za). Ca compile maintenant.


    Si t'utilises VS2010 n'utilise pas /Za l'option est bugguée. :

    http://lists.boost.org/Archives/boos.../04/165531.php

    (et le bug est vraiment méchant)
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  10. #10
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Arf.

    Ceci dit, ça n'est pas lié à la spécialisation partielle :
    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
    template<class T> struct dense{};
     
    template<template<class T> class stockage, typename precision> class Vecteur : stockage<precision>
    {
    public:
                  // syntaxes valides si désactivation des extensions de langage
     
                  Vecteur<dense,precision> fun2(); 	
                  Vecteur<dense,int> fun3(); 
     
                  // syntaxes inconditionnellement valides
     
    	//Vecteur<::dense,precision> fun2(); 
    	//Vecteur<::dense,int> fun3(); 
    };
     
    int main()
    {
    	Vecteur<dense,double> toto;
       toto.fun2();
       toto.fun3();
    	return 0;
    }
    Ce qui me trouble quand même sur le comportement de VC

  11. #11
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template<typename precision> class Vecteur<dense,precision> : dense<precision>
    {
                // syntaxes valides si désactivation des extensions de langage
     
                Vecteur<dense,precision> fun2(); 	
                Vecteur<dense,int> fun3(); 
     
                // syntaxes inconditionnellement valides
     
    	Vecteur<::dense,precision> fun2(); 
    	Vecteur<::dense,int> fun3(); 
    };
    C'est étrange, on dirait qu'il réinjecte les noms des classes de bases de la classe dans celle-ci, comme pour le nom de la classe même. C'est standard comme comportement ?

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    C'est étrange, on dirait qu'il réinjecte les noms des classes de bases de la classe dans celle-ci, comme pour le nom de la classe même. C'est standard comme comportement ?
    Oui et non....
    L'injection se fait partout où elle est pertinente :
    Citation Envoyé par 14.6
    The injected-class-name of a class template or class template specialization can be used either with or without
    a template-argument-list wherever it is in scope. [Example:
    template <class T> struct Base {
    Base* p;
    };
    template <class T> struct Derived: public Base<T> {
    typename Derived::Base* p; // meaning Derived::Base<T>
    };
    Mais je pense que VC fait du zèle :
    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
    template<class T> struct dummy;
     
    template<class T, template<class> class U> 
    struct test : public U<T>
    {
        test<int,U> f1(); // ok
        test<int,dummy> f2(); // erreur
    };
     
    template<class T> struct dummy{};
     
    int main()
    {
       test<int,dummy> t;
     
       return 0;
    }

  13. #13
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Ca a du changer depuis alors, car d'après le Vandevoorde (9.2.3 page 127), ceci ne devrait pas compiler :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template<template<class> class> struct X {};
     
    template<class> struct C
    {
      X<C> c; //erreur, C sans arguments template n'est pas un template
      X< ::C> d; //ok, car C est "qualifié"
    };
    D'ou la similarité que je voyais avec les noms des classes de bases, mais je ne suis pas certain que les nioms des classes de bases doivent être injectées aussi.

    Pour l'exemple que tu montres, si tu définies la classe template dummy avant, ca marche ? (je n'ai pas VC pour tester) Si c'est le cas, ca ne pourrait pas être lié à l'ordre d'instanciation des différents templates ?

    Sinon je ne comprends pas trop comment un tel code ne pourrait pas compiler, il ne voit pas la classe template dummy depuis l'intérieur de la classe template test ? Ca serait quand même contraires aux règles du "name lookup", non ?

  14. #14
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Pour l'exemple que tu montres, si tu définies la classe template dummy avant, ca marche ? (je n'ai pas VC pour tester) Si c'est le cas, ca ne pourrait pas être lié à l'ordre d'instanciation des différents templates ?
    Non ça change rien.

    Citation Envoyé par Flob90 Voir le message
    Ca a du changer depuis alors, car d'après le Vandevoorde (9.2.3 page 127), ceci ne devrait pas compiler :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    template<template<class> class> struct X {};
     
    template<class> struct C
    {
      X<C> c; //erreur, C sans arguments template n'est pas un template
      X< ::C> d; //ok, car C est "qualifié"
    };
    D'ou la similarité que je voyais avec les noms des classes de bases, mais je ne suis pas certain que les nioms des classes de bases doivent être injectées aussi.
    L'exemple de Vandevoorde doit rester à jour à mon sens. VC sort une erreur, GCC un warning (avec -Weffc++).
    Dans l'exemple que tu cites, aucun des éléments n'est lié au symbole effectivement utilisé lors de l'instanciation finale. Alors que dans le code proposé par Aleph, si (cf ci-dessous)

    Citation Envoyé par Flob90 Voir le message
    Sinon je ne comprends pas trop comment un tel code ne pourrait pas compiler, il ne voit pas la classe template dummy depuis l'intérieur de la classe template test ? Ca serait quand même contraires aux règles du "name lookup", non ?
    Pour moi, Visual qui fait du zèle. Le symbole dummy de mon exemple est traité comme le symbole U<T>. De ce que je comprends dans la norme, le nom injecté devrait être U<T> en tant que U dans la définition générique de test et non dummy<T> en tant que dummy dans l'instanciation de test<T,dummy>

    Je ne suis pas sur d'arriver à me faire comprendre

    Mais si je reprends :
    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<class T> struct dummy;
     
    template<class T, template<class> class U>
    struct test : public U<T>
    {
     
        test<int,U> f1(); // 1
        test<int,dummy> f2(); // 2
    };
     
    template<class T> struct dummy{};
     
    int main()
    {
       test<int,dummy> t2;
     
       return 0;
    }
    j'aurais moins été surpris si l'erreur avait été dans (1) : test<int,U> f1();

  15. #15
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Je crois que je commence à comprendre ce que tu veux dire : VC prend le raccourci de faire l'injection au moment de l'instanciation, et donc il réinjecte dummy<int> sous le nom dummy, à la place de faire l'injection "avant" l'instanciation, et donc de réinjecter U<T> sous le nom U ?

    Mais du coup d'après ce que je comprend de la norme et du Vandevoorde (enfin de là où j'en suis, pas encore fini de le lire), le code juste devrait plutôt être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    //idem
     
    template<class T, template<class> class U>
    struct test : public U<T>
    {
        //"qualification" pour que U soit bien un template et pas le nom réinjecté
        test<int, ::U> f1(); // 1
        //rien, dummy n'a pas à être injecté et est bien un template
        test<int,dummy> f2(); // 2
    };
     
    //idem
    ?

  16. #16
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,

    Citation Envoyé par Flob90 Voir le message
    Je crois que je commence à comprendre ce que tu veux dire : VC prend le raccourci de faire l'injection au moment de l'instanciation, et donc il réinjecte dummy<int> sous le nom dummy, à la place de faire l'injection "avant" l'instanciation, et donc de réinjecter U<T> sous le nom U ?
    C'est comme ça que je le comprends.

    Citation Envoyé par Flob90 Voir le message
    Mais du coup d'après ce que je comprend de la norme et du Vandevoorde (enfin de là où j'en suis, pas encore fini de le lire), le code juste devrait plutôt être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    //idem
     
    template<class T, template<class> class U>
    struct test : public U<T>
    {
        //"qualification" pour que U soit bien un template et pas le nom réinjecté
        test<int, ::U> f1(); // 1
        //rien, dummy n'a pas à être injecté et est bien un template
        test<int,dummy> f2(); // 2
    };
     
    //idem
    ?
    C'est aussi ma première inclination. Cependant, ni VC ni GCC ni digital n'acceptent ::U : GCC (mingw 4.5.2) et Visual 10 sortent une erreur, Digital mars et Visual 9 plantent carrément . Je pense que cela vient du fait que U est un paramètre template de test. Ce qui n'est pas le cas du Vandevoorde qui utilise soit la classe en cours de définition (C) soit une class extérieure (X).

    D'une certaine façon, je ne serais pas étonné qu'un cas aussi tordu soit dans un trou de spec. Ce qui est décrit comme injecté ce sont les noms des types génériques comme instanciés avec leur(s) paramètre(s) template, pas le nom des paramètres template en tant que tel lorsqu'ils sont dans une position équivalente :

    Code Vandevoorde : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<template<class> class> struct X {};
    template<class T> struct C
    {
      X< ::C> c; // C'est C<T> qui est 'injecté' comme C. C n'est pas un nom de paramètre template mais un nom de type générique
    };

    Code norme : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <class T> struct Base {
        Base* p;
    };
    template <class T> struct Derived: public Base<T> {
        typename Base* p; // C'est Derived::Base<T> qui est injecté en tant que Base. Base n'est pas un nom paramètre template mains un nom de type générique
    };

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<class T, template<class> class U>
    struct test : public U<T>
    {
        test<int, U> f1(); // U<T> ne semble pas réinjecté en tant que U. U est un nom d'un des paramètres template.
        test<int,dummy> f2(); // dummy<T> est réinjecté en tant que dummy lorsque test est instancié en test<T,dummy>. Ceci me semble être une erreur.
    };
    Bon, j'va me renseigner du côté de comp.std.

Discussions similaires

  1. Valeur de retour d'une procédure stockée
    Par Rudyweb dans le forum MFC
    Réponses: 4
    Dernier message: 25/02/2005, 18h52
  2. fonction operator, valeur de retour
    Par butch dans le forum C++
    Réponses: 21
    Dernier message: 20/09/2004, 11h30
  3. [VB6] Valeur de retour pour une Form
    Par preverse dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 17/08/2004, 18h16
  4. Valeur de retour d'une procédure externe
    Par elekis dans le forum x86 32-bits / 64-bits
    Réponses: 4
    Dernier message: 16/04/2004, 17h45
  5. Pourquoi une seule valeur de retour pour les fonctions ?
    Par Bruno75 dans le forum Langages de programmation
    Réponses: 33
    Dernier message: 18/01/2004, 14h58

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