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 :

SFINAE. (je ne comprend pas)


Sujet :

Langage C++

Mode arborescent

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut SFINAE. (je ne comprend pas)
    Salut!

    J'arrive enfin au bout de mes peines avec mon système de sérialisation. (quoi que..., pas encore tout à fait!)

    Je n'ai trouvé d'autres solutions que d'appeler 4 fonction template différente ce qui est beaucoup (je sais) et je ne sais même pas si cela est possible avec SFINAE, je pense que c'est possible mais j'ai du manqué de compréhension.

    La 1ère fonction écrit des types fondamentaux en les insérant directement dans le flux, chacun sont séparé par un espace.
    La 2ème fonction écrit des std::string en les insérant directement dans le flux, chacun sont séparé par std::endl.
    La 3ème fonction écrit des objets statiques en appelant une méthode que je redéfini dans la classe de l'objet.
    La 4ème fonction écrit des objets dynamiques en appelant une méthode sur un objet (une clé) que j'insère dans la classe de l'objet à partir d'une macro. (Ceci me permet de récupéré le type dynamique à l'exécution et d'appeler la fonction de la bonne classe)

    Tout est sérialiser à partir de plusieurs archives qui contiennent le flux (exactement comme avec boost!) et je veux que cette archive choisisse la bonne fonction à appeler suivant le type de l'objet. (Ceci m'éviterais d'avoir des erreurs en compilation parce que l'objet ne contient pas de variable nommé key par exemple.)

    J'ai donc essayé de faire quelque chose comme ceci :

    Code cpp : 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
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
     
     template <class O,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value
                  && !std::is_fundamental<O>::value
                  && std::is_member_function_pointer<void(O::*)(OTextArchive&)>::value
                  && std::is_member_object_pointer<decltype(&O::key)>::value>::type>
        void operator() (O& object) {
            if (typeid(decltype(object)) == typeid(object)) {
                object.serialize(*this);
            } else {
                object.key.register_object(&object);
                object.key.serialize_object(*this, 0);
            }
        }
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<std::is_member_function_pointer<void(O::*)(OTextArchive&)>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O& object, D...) {
            object.serialize(*this);
        }
        template <class O,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value
                  && !std::is_fundamental<O>::value
                  && std::is_member_function_pointer<void(O::*)(OTextArchive&)>::value
                  && std::is_member_object_pointer<decltype(&O::key)>::value>::type>
        void operator() (O* object) {
            std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(reinterpret_cast<unsigned long long int>(object));
            if (it != adresses.end()) {
                buffer<<it->second<<" ";
            } else {
                int index = -1;
                std::pair<unsigned long long int, unsigned long long int> newAddress (reinterpret_cast<unsigned long long int>(object), nbSerialized);
                adresses.insert(newAddress);
                if (typeid(decltype(*object)) == typeid(*object)) {
                    std::cout<<"non polymoprhic version"<<std::endl;
                    buffer<<newAddress.second<<" ";
                    buffer<<index<<" ";
                    object->serialize(*this);
                } else {
                    std::cout<<"polymoprhic version"<<std::endl;
                    object->key.register_object(object);
                    index = object->key.getTypeIndex();
                    buffer<<newAddress.second<<" ";
                    buffer<<index<<" ";
                    object->key.serialize_object(*this, 0);
                }
                nbSerialized++;
            }
        }
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<std::is_member_function_pointer<void(O::*)(OTextArchive&)>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O* object) {
            std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(reinterpret_cast<unsigned long long int>(object));
            if (it != adresses.end()) {
                buffer<<it->second<<" ";
            } else {
                std::pair<unsigned long long int, unsigned long long int> newAddress (reinterpret_cast<unsigned long long int>(object), nbSerialized);
                adresses.insert(newAddress);
                buffer<<newAddress.second<<" ";
                object->serialize(*this);
                nbSerialized++;
            }
        }
        template <typename T,
              class... D,
              class = typename std::enable_if<std::is_fundamental<T>::value>::type,
              class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (T& data, D...) {
            buffer<<data<<" ";
        }
         template <typename T,
              class... D,
              class = typename std::enable_if<!std::is_fundamental<T>::value>::type,
              class = typename std::enable_if<std::is_same<T, std::string>::value>::type,
              class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (T& data, D...) {
            buffer<<data<<"\n";
        }
        template <typename T,
              class... D,
              class = typename std::enable_if<std::is_fundamental<T>::value>::type,
              class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (T* data, D...) {
            std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(reinterpret_cast<unsigned long long int>(data));
            if (it != adresses.end()) {
                buffer<<it->second;
            } else {
                std::pair<unsigned long long int, unsigned long long int> newAddress (reinterpret_cast<unsigned long long int>(data), nbSerialized);
                adresses.insert(newAddress);
                buffer<<newAddress.second;
                buffer<<*data<<" ";
                nbSerialized++;
            }
        }
        template <typename T,
              class... D,
              class = typename std::enable_if<std::is_fundamental<T>::value>::type,
              class = typename std::enable_if<std::is_same<T, std::string>::value>::type,
              class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (T* data, D...) {
            std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(reinterpret_cast<unsigned long long int>(data));
            if (it != adresses.end()) {
                buffer<<it->second;
            } else {
                std::pair<unsigned long long int, unsigned long long int> newAddress (reinterpret_cast<unsigned long long int>(data), nbSerialized);
                adresses.insert(newAddress);
                buffer<<newAddress.second;
                buffer<<*data<<"\n";
                nbSerialized++;
            }
        }
        template <class O,
                  class = typename std::enable_if<std::is_member_function_pointer<void(O::*)(OTextArchive&)>::value && !std::is_polymorphic<O>::value && !std::is_same<O, std::string>::value>::type>
        void operator() (std::vector<O>& data) {
            std::size_t size = data.size();
            buffer<<size;
            for (unsigned int i = 0; i < data.size(); i++)
                 (*this)(data[i]);
        }

    Donc je veux que :

    Si l'objet n'est pas un type fondamental, ni un string, contient un pointeur de fonction prenant l'archive en paramètre et ne contient pas de variable nommé key, alors il me choisisse la 1ère fonction.

    Sinon si l'objet n'est pas un type fondamental, ni un string, contient un pointeur de fonction prenant l'archive en paramètre et contient une variable nommé key, alors il me choississe la deuxième fonction.

    Sinon si l'objet est un type fondamental il me choisisse la troisième fonction.

    Sinon si l'objet n'est pas un type fondamental mais un string, il me choisisse la dernière fonction.

    Malheureusement ça ne fonctionne pas, il me choisi la mauvaise fonction, par exemple, pour un type fondamental, il me choisi la 1ère et non pas la troisième :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    ||=== Build: Debug in ODFAEG-DEMO (compiler: GNU GCC Compiler) ===|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|9|warning: "G2DEKEY" redefined [enabled by default]|
    /usr/local/include/odfaeg/Graphics/2D/entity.h|13|note: this is the location of the previous definition|
    /usr/local/include/odfaeg/Core/archive.h||In instantiation of ‘void odfaeg::OTextArchive::operator()(O&, D ...) [with O = std::vector<unsigned char>; D = {}; <template-parameter-1-3> = void; <template-parameter-1-4> = void; <template-parameter-1-5> = void; <template-parameter-1-6> = void]’:|
    /usr/local/include/odfaeg/Graphics/image.hpp|257|required from ‘void odfaeg::Image::serialize(Archive&) [with Archive = odfaeg::OTextArchive]’|
    /usr/local/include/odfaeg/Core/archive.h|103|required from ‘void odfaeg::OTextArchive::operator()(O&, D ...) [with O = odfaeg::Image; D = {}; <template-parameter-1-3> = void; <template-parameter-1-4> = void; <template-parameter-1-5> = void; <template-parameter-1-6> = void]’|
    /usr/local/include/odfaeg/Graphics/texture.h|474|required from ‘void odfaeg::Texture::serialize(Archive&) [with Archive = odfaeg::OTextArchive]’|
    /usr/local/include/odfaeg/Core/archive.h|103|required from ‘void odfaeg::OTextArchive::operator()(O&, D ...) [with O = odfaeg::Texture; D = {}; <template-parameter-1-3> = void; <template-parameter-1-4> = void; <template-parameter-1-5> = void; <template-parameter-1-6> = void]’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|26|required from here|
    /usr/local/include/odfaeg/Core/archive.h|103|error: ‘class std::vector<unsigned char>’ has no member named ‘serialize’|
    ||=== Build failed: 1 error(s), 7 warning(s) (0 minute(s), 2 second(s)) ===|
    Bref je ne comprend pas pourquoi le compilateur me choisi cette fonction (hors que la condition est fausse) plutôt que la 3ème.
    Sinon, comment faire pour que le compilateur me choisisse bien les bonnes fonctions.

    Merci d'avance pour vos réponses.
    Dernière modification par Invité ; 18/08/2014 à 10h15.

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

Discussions similaires

  1. Erreur Objet requis : 'this' --> Comprend pas!!
    Par Grozeil dans le forum ASP
    Réponses: 3
    Dernier message: 30/03/2005, 09h46
  2. [thread][methodologie]Quelque chose que je ne comprends pas!
    Par norkius dans le forum Général Java
    Réponses: 5
    Dernier message: 16/03/2005, 14h01
  3. sql ne comprend pas mon where!et me demande des parametres
    Par marie10 dans le forum Langage SQL
    Réponses: 10
    Dernier message: 20/04/2004, 11h08
  4. [Rave] un message que je ne comprends pas
    Par Clotilde dans le forum Rave
    Réponses: 2
    Dernier message: 30/09/2003, 21h46

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