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 :

Comment passer un pointeur (d'un std::unique_ptr) à une fonction template ?


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Comment passer un pointeur (d'un std::unique_ptr) à une fonction template ?
    Salut, j'essaye d'extraire le pointeur d'un std::unique_ptr et de le passer à une fonction template comme ceci :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template <class T>
        void operator() (std::unique_ptr<T>& ptr) {
            (*this)(ptr.get());
        }

    Afin d'éviter à avoir à réécrire deux fois le même code dans le cas ou je passe un pointeur nu et dans le cas ou je passe un std::unique_ptr.

    Malheureusement, cela ne fonctionne pas et j'ai cette erreur en compilation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    /home/laurent/Développement/Projets-c++/ODFAEG/src/odfaeg/Physics/../../../include/odfaeg/Physics/../Math/../Core/archive.h|889|error: no match for call to ‘(odfaeg::ITextArchive) (std::unique_ptr<odfaeg::BoundingVolume>::pointer)’|
    Comment puis je passer le pointer d'un pointeur intelligent à une fonction template ?

    Merci d'avance pour votre aide.

  2. #2
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    Peut-être as tu mal declaré le premier operateur ?

    Ceci marche :

    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
    //==============================================================================
    #include <iostream>
    #include <memory>
    //==============================================================================
    struct A
    {
        template <class T>
        void operator()(T* ptr) const { std::cout << "ok" << std::endl; }
     
        template <class T>
        void operator() (std::unique_ptr<T>& ptr) const
        {
            (*this)(ptr.get());
        }
    };
    //------------------------------------------------------------------------------
    int main()
    {
        std::unique_ptr<int> uptr(new int(6));
        int* ptr = new int(5);
        A a;
        a(uptr); //ok
        a(ptr);  //ok
        return 0;
    }
    //==============================================================================

  3. #3
    Invité
    Invité(e)
    Par défaut
    Re,

    voici comment j'ai rédigé le tout :

    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
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
     
     //Fundamentals.
        /**
        * \fn void operator(T& data, D...)
        * \brief read a fundamental type from the archive.
        * \param T& the data to read.
        * \param D... used for SFINAE.
        */
        template <typename T,
              class... D,
              class = typename std::enable_if<std::is_fundamental<T>::value>::type>
        void operator() (T& data, D...) {
             buffer>>data;
             char space;
             buffer.get(space);
        }
        /**
        * \fn void operator(T& data, D...)
        * \brief read a char from the archive. (we need to read unformatted input here to also read special chars like \n, spaces, etc...)
        * \param T& the data to read.
        * \param D... used for SFINAE.
        */
        void operator() (char& data) {
             buffer.get(data);
             char space;
             buffer.get(space);
        }
        /**
        * \fn void operator(T& data, D...)
        * \brief read an unsigned char from the archive. (we need to read unformatted input here to also read special chars like \n, spaces, etc...)
        * \param T& the data to read.
        * \param D... used for SFINAE.
        */
        void operator() (unsigned char& data) {
             buffer.get((char&) data);
             char space;
             buffer.get(space);
        }
     
        /**
        * \fn void operator(T& data, D...)
        * \brief read a pointer to a fundamental type from the archive.
        * \param T& the data to read.
        * \param D... used for SFINAE.
        */
        template <typename T,
              class... D,
              class = typename std::enable_if<std::is_fundamental<T>::value>::type>
        void operator() (T*& data, D...) {
            unsigned long long int id;
            buffer>>id;
            char space;
            buffer.get(space);
            if (id != -1) {
                std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(id);
                if (it != adresses.end()) {
                    data = reinterpret_cast<T*> (it->second);
                } else {
                    data = new T();
                    (*this)(*data);
                    std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(data));
                    adresses.insert(newAddress);
                    nbDeserialized++;
                }
            }
        }
        template <typename E,
                class... D,
                class = typename std::enable_if<!std::is_fundamental<E>::value>::type,
                class = typename std::enable_if<std::is_enum<E>::value>::type>
        void operator()(E& data, D...) {
            int eVal;
            buffer>>eVal;
            data = static_cast<E>(eVal);
            char space;
            buffer.get(space);
        }
        template <typename E,
                class... D,
                class = typename std::enable_if<!std::is_fundamental<E>::value>::type,
                class = typename std::enable_if<std::is_enum<E>::value>::type>
        void operator() (E*& data, D...) {
            unsigned long long int id;
            buffer>>id;
            char space;
            buffer.get(space);
            if (id != -1) {
                std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(id);
                if (it != adresses.end()) {
                    data = reinterpret_cast<E*> (it->second);
                } else {
                    data = new E();
                    (*this)(*data);
                    std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(data));
                    adresses.insert(newAddress);
                    nbDeserialized++;
                }
            }
        }
        //std::string.
        /**
        * \fn void operator(T& data, D...)
        * \brief read an std::string from the archive.
        * \param T& the data to read.
        * \param D... used for SFINAE.
        */
        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<!std::is_enum<T>::value>::type>
        void operator() (T& data, D...) {
            std::vector<char> vDatas;
            (*this)(vDatas);
            const char* datas = &vDatas[0];
            std::size_t str_size = vDatas.size();
            data = std::string(datas, str_size);
        }
        /**
        * \fn void operator(T& data, D...)
        * \brief read a pointer to an std::string from the archive.
        * \param T* the data to read.
        * \param D... used for SFINAE.
        */
        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<!std::is_enum<T>::value>::type>
        void operator() (T*& data, D...) {
            unsigned long long int id;
            buffer>>id;
            char space;
            buffer.get(space);
            if (id != -1) {
                std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(id);
                if (it != adresses.end()) {
                    data = reinterpret_cast<T*> (it->second);
                } else {
                    data = new T();
                    (*this)(*data);
                    std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(data));
                    adresses.insert(newAddress);
                    nbDeserialized++;
                }
            }
        }
        //Static objects.
        /**
        * \fn void operator(O& data, D...)
        * \brief read a static object from the archive.
        * \param O& the data to read.
        * \param D... used for SFINAE.
        */
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value && !std::is_pointer<O>::value>::type,
                  class = typename std::enable_if<!has_typedef_key<O>::value>::type,
                  class = typename std::enable_if<!std::is_enum<O>::value>::type>
        void operator() (O& object, D...) {
            object.serialize(*this);
        }
        /**
        * \fn void operator(O& data, D...)
        * \brief read a pointer to a static object from the archive.
        * \param O* the data to read.
        * \param D... used for SFINAE.
        */
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<!has_typedef_key<O>::value>::type,
                  class = typename std::enable_if<!std::is_enum<O>::value>::type>
        void operator() (O*& object, D...) {
            unsigned long long int id;
            buffer>>id;
            char space;
            buffer.get(space);
            if (id != -1) {
                std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(id);
                if (it != adresses.end()) {
                    object = reinterpret_cast<O*>(it->second);
                } else {
                    object = new O();
                    object->serialize(*this);
                    std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(object));
                    adresses.insert(newAddress);
                    nbDeserialized++;
                }
            }
        }
        //Dynamic objects.
        /**
        * \fn void operator(O* data, D...)
        * \brief read a dynamic object from the archive.
        * \param O& the data to read.
        * \param D... used for SFINAE.
        */
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<has_typedef_key<O>::value>::type,
                  class = typename std::enable_if<!std::is_enum<O>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O& object, D...) {
            if (typeid(decltype(object)) == typeid(object)) {
                object.vtserialize(*this);
            } else {
                object.key.register_object(&object);
                object.key.serialize_object("serialize", "ITextArchive", *this);
            }
        }
        /**
        * \fn void operator(O* data, D...)
        * \brief read a pointer to a non abstract dynamic object from the archive.
        * \param O* the data to read.
        * \param D... used for SFINAE.
        */
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<!std::is_enum<O>::value>::type,
                  class = typename std::enable_if<has_typedef_key<O>::value && !std::is_abstract<O>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O*& object, D...) {
            unsigned long long int id;
            std::string typeName;
            buffer>>id;
            char space;
            buffer.get(space);
            if (id != -1) {
                getline(buffer, typeName);
                std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(id);
                if (it != adresses.end()) {
                    object = reinterpret_cast<O*>(it->second);
                } else {
                    if (typeName == "BaseType") {
                         object = new O();
                         object->vtserialize(*this);
                        std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(object));
                        adresses.insert(newAddress);
                    } else {
                        object = O::allocate(typeName);
                        object->key.register_object(object);
                        object->key.serialize_object("serialize", "ITextArchive", *this);
                        std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(object));
                        adresses.insert(newAddress);
                    }
                    nbDeserialized++;
                }
            }
        }
        /**
        * \fn void operator(O* data, D...)
        * \brief read a pointer to an abstract dynamic object from the archive.
        * \param O* the data to read.
        * \param D... used for SFINAE.
        */
        template <class O,
                  class... D,
                  class = typename std::enable_if<!std::is_fundamental<O>::value>::type,
                  class = typename std::enable_if<!std::is_same<O, std::string>::value>::type,
                  class = typename std::enable_if<!std::is_enum<O>::value>::type,
                  class = typename std::enable_if<has_typedef_key<O>::value>::type,
                  class = typename std::enable_if<std::is_abstract<O>::value>::type,
                  class = typename std::enable_if<!sizeof...(D)>::type>
        void operator() (O*& object, D...) {
            std::string typeName;
            unsigned long long int id;
            buffer>>id;
            if (id != -1) {
                char space;
                buffer.get(space);
                getline(buffer, typeName);
                std::map<unsigned long long int, unsigned long long int>::iterator it = adresses.find(id);
                if (it != adresses.end()) {
                    object = reinterpret_cast<O*>(it->second);
                } else {
                    object = O::allocate(typeName);
                    object->key.register_object(object);
                    object->key.serialize_object("serialize", "ITextArchive", *this);
                    std::pair<unsigned long long int, unsigned long long int> newAddress (id, reinterpret_cast<unsigned long long int>(object));
                    adresses.insert(newAddress);
                    nbDeserialized++;
                }
            }
        }
        /**
        * \fn void operator(O* data, D...)
        * \brief read a list of objects from the archive.
        * \param O* the data to read.
        * \param D... used for SFINAE.
        */
        template <class O>
        void operator() (std::vector<O>& objects) {
            std::size_t size;
            buffer>>size;
            char space;
            buffer.get(space);
            for (unsigned int i = 0; i < size; i++) {
                O object;
                (*this)(object);
                objects.push_back(object);
            }
        }
        template <class T>
        void operator() (std::unique_ptr<T>& ptr) {
            (*this)(ptr.get());
        }
        template <class T>
        void operator() (std::shared_ptr<T>& ptr) {
            (*this)(ptr.get());
        }

    Il semblerait qu'il ne trouve pas la bonne version de l'operateur () et je ne vois pas pourquoi, pourtant, en passant des pointeurs nu à l'opérateur () cela compile sans problèmes.

    Il recherche l'operator() pour le type std::unique_ptr<T>::pointer et pas pour le type T*.

    PS : Et puis osef je vais passer un std::vector avec des pointeurs nus, ça sera plus simple :
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    std::vector<BoundingVolume*> getChildren() {
            std::vector<BoundingVolume*> bv;
            for (unsigned int i = 0; i < children.size(); i++)
                bv.push_back(children[i].get());
            return bv;
         }

  4. #4
    Invité
    Invité(e)
    Par défaut
    On dirait, qu'il n'apprécie pas lorsque j'essaye d'instancier le pointeur en dehors du wrapper :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    template <typenane T>
    void operator()(T*& t) {
           t = new T();
    }
    template <typename T>
    void operator(std::unique_ptr<T>& ptr) {
          (*this)(ptr.get());
    }

    Ce qui est plutôt gênant lorsque j'ai besoin de faire mon propre type d'allocator comme par exemple avec la classe std::vector.

    PS :

    je ne vois plus que deux solutions,la première c'est de passer une variable supplémentaire à l'allocateur générique et d'allouer soit avec std::make_unique, soit avec std::make_shared ou bien soit avec new.

    La second, c'est d'utiliser ma propre classe pour les pointeurs intelligent, je ne sais pas laquelle est la meilleure, je pencherais plutôt pour la 1ère non ?
    Dernière modification par Invité ; 03/10/2014 à 14h42.

  5. #5
    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
    Donnes le message d'erreur en entier, normalement ton compilo te dit pourquoi il ne peut pas choisir les différentes surcharges (c'est tout les messages commençant par note : à la suite du message error).

  6. #6
    Invité
    Invité(e)
    Par défaut
    J'ai en effet pleins de message du style note :

    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
     
    ||=== Build: Debug in ODFAEG-DEMO (compiler: GNU GCC Compiler) ===|
    /usr/local/include/odfaeg/Core/archive.h||In instantiation of ‘void odfaeg::ITextArchive::operator()(std::unique_ptr<_Tp>&) [with T = odfaeg::BoundingVolume]’:|
    /usr/local/include/odfaeg/Core/archive.h|883|required from ‘void odfaeg::ITextArchive::operator()(std::vector<_RealType>&) [with O = std::unique_ptr<odfaeg::BoundingVolume>]’|
    /usr/local/include/odfaeg/Physics/boundingVolume.h|85|required from ‘void odfaeg::BoundingVolume::vtserialize(Archive&) [with Archive = odfaeg::ITextArchive]’|
    /usr/local/include/odfaeg/Physics/boundingBox.h|144|required from ‘void odfaeg::BoundingBox::vtserialize(Archive&) [with Archive = odfaeg::ITextArchive]’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|4|required from here|
    /usr/local/include/odfaeg/Core/archive.h|889|error: no match for call to ‘(odfaeg::ITextArchive) (std::unique_ptr<odfaeg::BoundingVolume>::pointer)’|
    /usr/local/include/odfaeg/Core/archive.h|540|note: candidates are:|
    /usr/local/include/odfaeg/Core/archive.h|589|note: template<class T, class ... D, class> void odfaeg::ITextArchive::operator()(T&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|589|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|588|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|600|note: void odfaeg::ITextArchive::operator()(char&)|
    /usr/local/include/odfaeg/Core/archive.h|600|note:   no known conversion for argument 1 from ‘std::unique_ptr<odfaeg::BoundingVolume>::pointer {aka odfaeg::BoundingVolume*}’ to ‘char&’|
    /usr/local/include/odfaeg/Core/archive.h|611|note: void odfaeg::ITextArchive::operator()(unsigned char&)|
    /usr/local/include/odfaeg/Core/archive.h|611|note:   no known conversion for argument 1 from ‘std::unique_ptr<odfaeg::BoundingVolume>::pointer {aka odfaeg::BoundingVolume*}’ to ‘unsigned char&’|
    /usr/local/include/odfaeg/Core/archive.h|626|note: template<class T, class ... D, class> void odfaeg::ITextArchive::operator()(T*&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|626|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|625|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|648|note: template<class E, class ... D, class, class> void odfaeg::ITextArchive::operator()(E&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|648|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|647|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|659|note: template<class E, class ... D, class, class> void odfaeg::ITextArchive::operator()(E*&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|659|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|658|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|689|note: template<class T, class ... D, class, class, class> void odfaeg::ITextArchive::operator()(T&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|689|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|687|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|707|note: template<class T, class ... D, class, class, class> void odfaeg::ITextArchive::operator()(T*&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|707|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|705|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|738|note: template<class O, class ... D, class, class, class, class> void odfaeg::ITextArchive::operator()(O&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|738|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|735|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|753|note: template<class O, class ... D, class, class, class, class> void odfaeg::ITextArchive::operator()(O*&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|753|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|751|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|785|note: template<class O, class ... D, class, class, class, class, class> void odfaeg::ITextArchive::operator()(O&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|785|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|782|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|806|note: template<class O, class ... D, class, class, class, class, class> void odfaeg::ITextArchive::operator()(O*&, D ...)|
    /usr/local/include/odfaeg/Core/archive.h|806|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|804|error: no type named ‘type’ in ‘struct std::enable_if<false, void>’|
    /usr/local/include/odfaeg/Core/archive.h|848|note: void odfaeg::ITextArchive::operator()(O*&, D ...) [with O = odfaeg::BoundingVolume; D = {}; <template-parameter-1-3> = void; <template-parameter-1-4> = void; <template-parameter-1-5> = void; <template-parameter-1-6> = void; <template-parameter-1-7> = void; <template-parameter-1-8> = void]|
    /usr/local/include/odfaeg/Core/archive.h|848|note:   no known conversion for argument 1 from ‘std::unique_ptr<odfaeg::BoundingVolume>::pointer {aka odfaeg::BoundingVolume*}’ to ‘odfaeg::BoundingVolume*&’|
    /usr/local/include/odfaeg/Core/archive.h|876|note: template<class O> void odfaeg::ITextArchive::operator()(std::vector<_RealType>&)|
    /usr/local/include/odfaeg/Core/archive.h|876|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|889|note:   mismatched types ‘std::vector<_RealType>’ and ‘std::unique_ptr<odfaeg::BoundingVolume>::pointer {aka odfaeg::BoundingVolume*}’|
    /usr/local/include/odfaeg/Core/archive.h|888|note: template<class T> void odfaeg::ITextArchive::operator()(std::unique_ptr<_Tp>&)|
    /usr/local/include/odfaeg/Core/archive.h|888|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|889|note:   mismatched types ‘std::unique_ptr<_Tp>’ and ‘std::unique_ptr<odfaeg::BoundingVolume>::pointer {aka odfaeg::BoundingVolume*}’|
    /usr/local/include/odfaeg/Core/archive.h|892|note: template<class T> void odfaeg::ITextArchive::operator()(std::shared_ptr<_Tp1>&)|
    /usr/local/include/odfaeg/Core/archive.h|892|note:   template argument deduction/substitution failed:|
    /usr/local/include/odfaeg/Core/archive.h|889|note:   mismatched types ‘std::shared_ptr<_Tp1>’ and ‘std::unique_ptr<odfaeg::BoundingVolume>::pointer {aka odfaeg::BoundingVolume*}’|
    /usr/include/c++/4.9/ext/new_allocator.h||In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::unique_ptr<odfaeg::BoundingVolume>; _Args = {const std::unique_ptr<odfaeg::BoundingVolume, std::default_delete<odfaeg::BoundingVolume> >&}; _Tp = std::unique_ptr<odfaeg::BoundingVolume>]’:|
    /usr/include/c++/4.9/bits/alloc_traits.h|253|required from ‘static std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::unique_ptr<odfaeg::BoundingVolume>; _Args = {const std::unique_ptr<odfaeg::BoundingVolume, std::default_delete<odfaeg::BoundingVolume> >&}; _Alloc = std::allocator<std::unique_ptr<odfaeg::BoundingVolume> >; std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> = void]’|
    /usr/include/c++/4.9/bits/alloc_traits.h|399|required from ‘static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::unique_ptr<odfaeg::BoundingVolume>; _Args = {const std::unique_ptr<odfaeg::BoundingVolume, std::default_delete<odfaeg::BoundingVolume> >&}; _Alloc = std::allocator<std::unique_ptr<odfaeg::BoundingVolume> >; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]’|
    /usr/include/c++/4.9/bits/stl_vector.h|918|required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr<odfaeg::BoundingVolume>; _Alloc = std::allocator<std::unique_ptr<odfaeg::BoundingVolume> >; std::vector<_Tp, _Alloc>::value_type = std::unique_ptr<odfaeg::BoundingVolume>]’|
    /usr/local/include/odfaeg/Core/archive.h|884|required from ‘void odfaeg::ITextArchive::operator()(std::vector<_RealType>&) [with O = std::unique_ptr<odfaeg::BoundingVolume>]’|
    /usr/local/include/odfaeg/Physics/boundingVolume.h|85|required from ‘void odfaeg::BoundingVolume::vtserialize(Archive&) [with Archive = odfaeg::ITextArchive]’|
    /usr/local/include/odfaeg/Physics/boundingBox.h|144|required from ‘void odfaeg::BoundingBox::vtserialize(Archive&) [with Archive = odfaeg::ITextArchive]’|
    /home/laurent/Développement/Projets-c++/ODFAEG-DEMO/main.cpp|4|required from here|
    /usr/include/c++/4.9/ext/new_allocator.h|120|error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = odfaeg::BoundingVolume; _Dp = std::default_delete<odfaeg::BoundingVolume>]’|
    /usr/include/c++/4.9/bits/unique_ptr.h|356|note: declared here|
    ||=== Build failed: 12 error(s), 13 warning(s) (0 minute(s), 10 second(s)) ===|
    PS : sinon j'ai pensé à ceci en passant un entier à mon allocateur, et en utilisant std::integral_constant, ensuite je passe cet entier à la classe EXPORT_CLASS_GUID pour savoir quel allocateur utilise (celui pour le std::unique_ptr, celui pour le std::shared_ptr ou celui pour le raw_ptr) pour instancier le pointeur sur le type de la classe.

    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
     
    /**\class Allocator
    *  \brief this struct allocate an object of a derived type and return a pointer of the base type.
    *  \param B : the base type.
    */
    template <typename B>
    struct Allocator {
     
       /**\fn allocate(D*)
       *  \brief this function allocates an object of a derived type and return a pointer of the base type.
       *  \param D : the derived type.
       *  \return B* : a pointer to the base type.
       */
       template <typename D, int I, typename BL, class = std::integral_constant<bool, 0>>
       B* allocate(D*, BL) {
            return new D();
       }
       template <typename D, int I, typename BL, class = std::integral_constant<bool, 1>>
       std::unique_ptr<B>&& allocate(D*, BL) {
           std::unique_ptr<B> ptr = std::make_unique<D>();
           return std::move(ptr);
       }
       template <typename D, int I, typename BL, class = std::integral_constant<bool, 2>>
       std::shared_ptr<B>&& allocate(D*, BL) {
           std::shared_ptr<B> ptr = std::make_shared<D>();
           return std::move(ptr);
       }
    };

    En héritant de Allocator<B> je pourrais peut être faire mon propre type d'allocateur en redéfinissant la méthode allocate, je pense que ça serait, pas mal!

  7. #7
    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 essaies de prendre tes pointeurs par lvalue référence, or get retourne un simple pointeur, donc l'expression ptr.get() est une rvalue, elle ne peut être attaché à une lvalue référence.

  8. #8
    Invité
    Invité(e)
    Par défaut
    Erf, c'est un petit peu gênant, surtout que je veux passer, une référence sur l'adresse du pointeur, sinon, celui-ci n'est allouer que localement dans la fonction qui appelle le new, mais reste null dans la fonction externe.

    De plus la référence me permet de pouvoir me passer du symbole & ce qui me permet d'écrire directement ceci pour OTestArchive et ITextArchive :
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename Archive>
    void vtserialize(Archive& ar) {
            ar(ptr);
            ar(valeur);
    }

    Au lieu de devoir faire cela qui est plus moche :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename Archive>
    void vtserialize(Archive& ar) {
            ar(&ptr);
            ar(valeur);
    }

    Et il est impossible de passer une rvalue reference sur une adresse...
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    template <class T>
        void operator() (std::unique_ptr<T>& ptr) {
            (*this)(std::move(&ptr.get()));
        }

    Mmm, comment faire...

    Ne vaudrait t'il pas mieux, travailler avec des pointeurs nu dans le cas ou on aurait besoin d'utiliser une référence sur un pointeur ou bien un double pointeur ?

  9. #9
    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 passes un référence sur le pointeur pour pouvoir l'allouer ? Dans ce cas là c'est un problème de logique, unique_ptr est fait pour gérer une ressource alloué, c'est normale qu'il ne te donne pas de quoi allouer ce qui devrait déjà l'être.

    Non, travailler avec des pointeurs nus si tu dois gérer la libération des ressources c'est une mauvaises idée.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Ok hé bah alors je pense que je vais opter pour la solution qui utilise un allocateur personnalisé, en passant, un id pour l'allocateur.

  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
    Tu as raison, fait un truc compliqué plutôt que d'essayer d'avoir une utilisation logique ...

  12. #12
    Invité
    Invité(e)
    Par défaut
    Bref, c'est un petit peu gênant, dans la mesure ou je dois écrire des std::unique_ptr et des std::shared_ptr dans un fichier pour ensuite les lire.

    De plus ce sont deux types différents donc une spécialisation pour chaque type de pointeurs, (sans pouvoir réutiliser ce qui existe déjà pour les rawpointer en passant la propriété du raw pointer au std::unique_ptr ou bien au std::shared_ptr qui lui, se chargera de le delete.)

    Ce qui fait que je devrais ré-écrire, toutes mes fonctions qui lisent des pointers sur des objets, des types primitifs, des énumérations, etc... pour std::unique_ptr et std::shared_ptr.

    Hors que j'en ai des toutes faîtes qui allouent et lisent des raw-pointers sur des objets, des types primitifs, des énumérations, etc..., ce qui n'est, pas très compliqué à faire, mais, demanderais beaucoup trop de redéfinition hors que j'aurai pu utilisé ce qui existe déjà.

    Mais bon si il faut que je fasse comme ça, autant faire comme ça, même si c'est, vachement plus lourd que de réutiliser ce qui existe déjà.

    Sinon à part ça oui il est vrai que ce n'est pas très logique d'allouer un std::unique_ptr avec pointeur déjà alloué. (Et même en déplaçant le raw_pointer avec std::move) cela ne compile pas non plus, bref, il n'y a aucun moyen de changer la propriété pour un raw_ptr.

  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
    Je comprends rien à ce que tu viens de raconter. Mais c'est la logique que tu mets en place le problème, pas les objectifs et les outils.

    Sérialiser un unique_ptr c'est pas très compliqué, je suppose que tu as les fonctions pour des pointeurs nus, ça donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    Archive& operator<<(Archive&,T*);
    Archive& operator>>(Archive&,T*&);
     
    Archive& operator<<(Archive& ar, const std::unique_ptr<T>& ptr)
    { return ar << ptr.get(); }
     
    Archive& operator>>(Archive& ar, std::unique_ptr<T>& ptr)
    {
        T* n_ptr;
        ar >> n_ptr;
        ptr.reset(n_ptr);
    }

  14. #14
    Invité
    Invité(e)
    Par défaut
    Bizarre, car j'ai essayé aussi cela mais ça ne compilait pas avec reset, il m'indique error, use of deleted function...

    J'ai oublié de précisé, ce n'est pas un std::unique_ptr que j'essaye de sérialiser mais un std::vector de std::unique_ptr, mais bref ça ne change rien, car je rappelle l'opérateur() pour chaque std::unique_ptr de monstd::vector.

    Du coup je suis passé par une classe pour faire mon propre système de pointeurs intelligent, qui ne se limite pas qu'à des pointeurs intelligent d'ailleurs mais à n'importe quel ressource chargée avec une fonction d'allocation.

  15. #15
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Comme unique_ptr... Qui ne se limite pas qu'à des pointeurs d'ailleurs mais à n'importe quels types. (second paramètre template de unique_ptr + définition du type pointer).

  16. #16
    Invité
    Invité(e)
    Par défaut
    Hum, tu n'aurais pas un exemple ?

  17. #17
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Par exemple, comme ressource des entiers et comme deleter une fonction de trace.

    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
    #include <algorithm>
    #include <iostream>
    #include <random>
    #include <memory>
    #include <array>
     
    class my_resource {
      int i;
     
    public:
      my_resource():i(0) {}
      my_resource(int n):i(n) {}
      bool operator == (std::nullptr_t) const { return i == 0; }
      bool operator != (std::nullptr_t) const { return !operator==(nullptr); }
      operator int () const { return i; }
    };
     
    // possible de spécifier std::default_delete pour ne pas le donner sysematiqueùent en template de unique_ptr et co
    struct trace_delete {
      using pointer = my_resource;
     
      void operator()(my_resource const & x) {
        std::cout << x << '\n';
      }
    };
     
     
    int main()
    {
      using U = std::unique_ptr<my_resource, trace_delete>;
      std::array<U, 5> a{{U(1), U(2), U(3), U(4), U(5)}};
      std::shuffle(a.begin(), a.end(), std::mt19937(std::random_device()()));
    }
    Le deleter peut aussi être partagé entre plusieurs unique_ptr si il est en référence dans la template.
    unique_ptr.

  18. #18
    Invité
    Invité(e)
    Par défaut
    Salut, mmm..., faudrait que j'essaye un truc du genre, bref, dans mon cas la ressource est template donc je ne sais pas si c'est possible, je pense qu'il me faudrait plutôt un allocateur comme pour la classe std::vector plutôt qu'un deleteur mais il semble que ça ne soit pas possible de passer un allocateur à std::unique_ptr et à std::shared_ptr.

    A moins que i soit l'adresse du pointeur, et qu'il faut passer, l'adresse du pointeur sur la ressource au deleter ?

    Mais apparemment non. :/
    Dernière modification par Invité ; 05/10/2014 à 10h43.

  19. #19
    Invité
    Invité(e)
    Par défaut
    Ce qui aurait été bien c'est de pouvoir, passer une fonction d'allocation à std::make_unique.

  20. #20
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Lolilolight Voir le message
    Salut, mmm..., faudrait que j'essaye un truc du genre, bref, dans mon cas la ressource est template donc je ne sais pas si c'est possible, je pense qu'il me faudrait plutôt un allocateur comme pour la classe std::vector plutôt qu'un deleteur mais il semble que ça ne soit pas possible de passer un allocateur à std::unique_ptr et à std::shared_ptr.
    Pour shared_ptr, il y a std::allocate_shared, qui est comme std::make_shared, mais avec un allocateur. Comme unique_ptr n'a rien besoin d'allouer, il n'y a pas de version avec allocateur.

    Par contre, je ne comprends pas ce que tu dis quand tu dis que ta ressource est template. Un unique_ptr peut pointer sur une instance d'un template, pas sur un template, donc je ne comprends pas ta phrase. Comme souvent, tu poses des question le long de ton chemin de réflexion, au lieu d'expliquer ton besoin initial, ce qui rend la réponse plus difficile, car on doit déjà comprendre ton bout de réflexion (qui a peut-être déjà des failles), et tu contrainds l'espace de réponse alors que la vraie réponse à ton besoin initial est peut-être en dehors de ces contraintes.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. Réponses: 8
    Dernier message: 29/07/2013, 18h30
  2. Réponses: 1
    Dernier message: 26/02/2008, 13h54
  3. Réponses: 15
    Dernier message: 25/06/2007, 10h35
  4. Réponses: 2
    Dernier message: 06/05/2007, 13h52
  5. Réponses: 2
    Dernier message: 26/09/2006, 09h56

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