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 :

Toujours cacher les types et les implémentations, oui mais


Sujet :

Langage C++

  1. #1
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 579
    Points
    218 579
    Billets dans le blog
    120
    Par défaut Toujours cacher les types et les implémentations, oui mais
    Bonjour à tous,

    Je viens de lire le GOTW 94 pour me remettre un peu dans le bain du C++, mais aussi pour voir pourquoi il était intéressant de toujours (ou presque toujours) utiliser le mot clé auto (Almost always auto Style).
    Bref, tout cela est très bien. L'exemple est clair dans ma tête, j'arrive à le saisir immédiatement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<class Container, class Value>
    void unique_append( Container& c, const Value& v ) {
        if( find(std::begin(c), std::end(c), v) == std::end(c) )
            c.emplace_back(v); 
        assert( !c.empty() );
    }
    Aucun soucis, j'avais très bien vu que l'on ne connaissait aucun type.
    Toutefois, je suis extrêmement perplexe par les concepts présentés dans le GOTW 94, surtout lorsque l'on me parle de :
    • Hiding code.
    • Hiding data (and code).
    • Hiding type (run-time polymorphism).
    • Hiding type (compile-time polymorphism).
    Moi, je suis du genre à ne pas savoir coder, ou du moins, à être vraiment distrait. Je me dit, c'est bien beau ce code, il est super généraliste, nickel c'est du vrai C++ (et moderne qui plus est). Par contre, un gars qui tombe sur ma fonction et qui essaie de l'utiliser avec un type perso, ou un type invalide (un type invalide étant un type de container ne possédant par de begin/end/empty/emplace_back dans ce cas), il va avoir ça :
    main.cpp: In instantiation of ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’:
    main.cpp:17:34: required from here
    main.cpp:7:5: error: no matching function for call to ‘end(const char*&)’
    main.cpp:7:5: note: candidates are:
    In file included from /usr/include/c++/4.7/utility:76:0,
    from /usr/include/c++/4.7/algorithm:61,
    from main.cpp:1:
    /usr/include/c++/4.7/initializer_list:99:5: note: template<class _Tp> constexpr const _Tp* std::end(std::initializer_list<_Tp>)
    /usr/include/c++/4.7/initializer_list:99:5: note: template argument deduction/substitution failed:
    main.cpp:7:5: note: mismatched types ‘std::initializer_list<_Tp>’ and ‘const char*’
    In file included from /usr/include/c++/4.7/string:53:0,
    from /usr/include/c++/4.7/random:41,
    from /usr/include/c++/4.7/bits/stl_algo.h:67,
    from /usr/include/c++/4.7/algorithm:63,
    from main.cpp:1:
    /usr/include/c++/4.7/bits/range_access.h:68:5: note: template<class _Container> decltype (__cont.end()) std::end(_Container&)
    /usr/include/c++/4.7/bits/range_access.h:68:5: note: template argument deduction/substitution failed:
    /usr/include/c++/4.7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.end()) std::end(_Container&) [with _Container = const char*]’:
    main.cpp:7:5: required from ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:68:5: error: request for member ‘end’ in ‘__cont’, which is of non-class type ‘const char*’
    main.cpp: In instantiation of ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’:
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:78:5: note: template<class _Container> decltype (__cont.end()) std::end(const _Container&)
    /usr/include/c++/4.7/bits/range_access.h:78:5: note: template argument deduction/substitution failed:
    /usr/include/c++/4.7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.end()) std::end(const _Container&) [with _Container = const char*]’:
    main.cpp:7:5: required from ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:78:5: error: request for member ‘end’ in ‘__cont’, which is of non-class type ‘const char* const’
    main.cpp: In instantiation of ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’:
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:97:5: note: template<class _Tp, long unsigned int _Nm> _Tp* std::end(_Tp (&)[_Nm])
    /usr/include/c++/4.7/bits/range_access.h:97:5: note: template argument deduction/substitution failed:
    main.cpp:7:5: note: mismatched types ‘_Tp [_Nm]’ and ‘const char*’
    main.cpp:7:5: error: no matching function for call to ‘begin(const char*&)’
    main.cpp:7:5: note: candidates are:
    In file included from /usr/include/c++/4.7/utility:76:0,
    from /usr/include/c++/4.7/algorithm:61,
    from main.cpp:1:
    /usr/include/c++/4.7/initializer_list:89:5: note: template<class _Tp> constexpr const _Tp* std::begin(std::initializer_list<_Tp>)
    /usr/include/c++/4.7/initializer_list:89:5: note: template argument deduction/substitution failed:
    main.cpp:7:5: note: mismatched types ‘std::initializer_list<_Tp>’ and ‘const char*’
    In file included from /usr/include/c++/4.7/string:53:0,
    from /usr/include/c++/4.7/random:41,
    from /usr/include/c++/4.7/bits/stl_algo.h:67,
    from /usr/include/c++/4.7/algorithm:63,
    from main.cpp:1:
    /usr/include/c++/4.7/bits/range_access.h:48:5: note: template<class _Container> decltype (__cont.begin()) std::begin(_Container&)
    /usr/include/c++/4.7/bits/range_access.h:48:5: note: template argument deduction/substitution failed:
    /usr/include/c++/4.7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.begin()) std::begin(_Container&) [with _Container = const char*]’:
    main.cpp:7:5: required from ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:48:5: error: request for member ‘begin’ in ‘__cont’, which is of non-class type ‘const char*’
    main.cpp: In instantiation of ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’:
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:58:5: note: template<class _Container> decltype (__cont.begin()) std::begin(const _Container&)
    /usr/include/c++/4.7/bits/range_access.h:58:5: note: template argument deduction/substitution failed:
    /usr/include/c++/4.7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.begin()) std::begin(const _Container&) [with _Container = const char*]’:
    main.cpp:7:5: required from ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:58:5: error: request for member ‘begin’ in ‘__cont’, which is of non-class type ‘const char* const’
    main.cpp: In instantiation of ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’:
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:87:5: note: template<class _Tp, long unsigned int _Nm> _Tp* std::begin(_Tp (&)[_Nm])
    /usr/include/c++/4.7/bits/range_access.h:87:5: note: template argument deduction/substitution failed:
    main.cpp:7:5: note: mismatched types ‘_Tp [_Nm]’ and ‘const char*’
    main.cpp:7:5: error: no matching function for call to ‘end(const char*&)’
    main.cpp:7:5: note: candidates are:
    In file included from /usr/include/c++/4.7/utility:76:0,
    from /usr/include/c++/4.7/algorithm:61,
    from main.cpp:1:
    /usr/include/c++/4.7/initializer_list:99:5: note: template<class _Tp> constexpr const _Tp* std::end(std::initializer_list<_Tp>)
    /usr/include/c++/4.7/initializer_list:99:5: note: template argument deduction/substitution failed:
    main.cpp:7:5: note: mismatched types ‘std::initializer_list<_Tp>’ and ‘const char*’
    In file included from /usr/include/c++/4.7/string:53:0,
    from /usr/include/c++/4.7/random:41,
    from /usr/include/c++/4.7/bits/stl_algo.h:67,
    from /usr/include/c++/4.7/algorithm:63,
    from main.cpp:1:
    /usr/include/c++/4.7/bits/range_access.h:68:5: note: template<class _Container> decltype (__cont.end()) std::end(_Container&)
    /usr/include/c++/4.7/bits/range_access.h:68:5: note: template argument deduction/substitution failed:
    /usr/include/c++/4.7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.end()) std::end(_Container&) [with _Container = const char*]’:
    main.cpp:7:5: required from ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:68:5: error: request for member ‘end’ in ‘__cont’, which is of non-class type ‘const char*’
    main.cpp: In instantiation of ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’:
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:78:5: note: template<class _Container> decltype (__cont.end()) std::end(const _Container&)
    /usr/include/c++/4.7/bits/range_access.h:78:5: note: template argument deduction/substitution failed:
    /usr/include/c++/4.7/bits/range_access.h: In substitution of ‘template<class _Container> decltype (__cont.end()) std::end(const _Container&) [with _Container = const char*]’:
    main.cpp:7:5: required from ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:78:5: error: request for member ‘end’ in ‘__cont’, which is of non-class type ‘const char* const’
    main.cpp: In instantiation of ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’:
    main.cpp:17:34: required from here
    /usr/include/c++/4.7/bits/range_access.h:97:5: note: template<class _Tp, long unsigned int _Nm> _Tp* std::end(_Tp (&)[_Nm])
    /usr/include/c++/4.7/bits/range_access.h:97:5: note: template argument deduction/substitution failed:
    main.cpp:7:5: note: mismatched types ‘_Tp [_Nm]’ and ‘const char*’
    main.cpp:7:5: error: ‘find’ was not declared in this scope
    main.cpp:7:5: note: suggested alternative:
    In file included from /usr/include/c++/4.7/algorithm:63:0,
    from main.cpp:1:
    /usr/include/c++/4.7/bits/stl_algo.h:4457:5: note: ‘std::find’
    main.cpp:8:9: error: request for member ‘emplace_back’ in ‘c’, which is of non-class type ‘const char*’
    main.cpp:9:5: error: request for member ‘empty’ in ‘c’, which is of non-class type ‘const char*’
    (GCC 4.6.3)
    j'ai plus de lignes d'erreurs que tout mon code.
    Jamais le compilateur ne m'indiquera vraiment où est la faute, mais où il voit la faute (dans la fonction, mais ça m'avance à "rien" de me dire que c n'a pas de fonction ...).

    Voici le code à l'origine de l'erreur :
    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
    #include <algorithm>
    #include <vector>
    #include <cassert>
     
    template<class Container, class Value>
    void unique_append( Container& c, const Value& v ) {
        if( find(std::begin(c), std::end(c), v) == std::end(c) )
            c.emplace_back(v); 
        assert( !c.empty() );
    }
     
    int main()
    {
        auto container = "Hello";
        auto value = int{42};
     
        unique_append(container,value);
     
        return 0;
    }
    Là, le main est simple, mais en mettant des auto partout sur le code, je me demande si cela ne deviendra pas simplement de plus en plus difficile de retrouver l'origine de l'erreur
    J'espère aussi (et j'attend vos retours) que les prochaines versions du compilateur donne de meilleurs résultats en terme de retour.

    Est-ce vraiment bien de se cacher tous les types ? Moi, je trouve juste que ça me fait des erreurs toujours plus illisible, jusqu'à même avoir des bibliothèques full C++11 inutilisables (oglplus).
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  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
    En faite le problème que tu observes sur les erreurs c'est surtout qu'il manque les concepts à l'heure actuel. Ils serait présents le message d'erreur pourrait être plus clair : "Erreur : Lors de l’instanciation, Container ne respecte pas le concept Truc. Détail : begin est requit par le concept et ne s'applique pas sur ce type.".

    On est un peu dans le même cas que les algorithmes de la bibliothèque standard quand il n'y avait pas les lambda : ça fonctionne mais ça pourrait être largement mieux.

  3. #3
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 579
    Points
    218 579
    Billets dans le blog
    120
    Par défaut
    Donc, il n'y aura pas d'amélioration sur ce point dans le C++ ?
    Y a t-il un autre moyen pour s'en sortir ?
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  4. #4
    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
    Si, les concepts sont prévus dans le futur.

    Cependant la forme des messages d'erreur, ce n'est pas seulement de la faute du langage, mais aussi du compilateur. Tu devrais tester ton code avec clang pour voir si le message est plus clair.

  5. #5
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Bonjour

    Le souci est probablement dans le code utilisateur qui ne réfléchit pas à ce qu'il fait (?)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    auto container = "Hello"; // En C++, on préfère les std::string ; donc on devrait avoir : std::string("Hello") ou "Hello"s en C++14
    auto value = int{42}; // Je préfère : int value = 42; (note : auto value = 42; fonctionne aussi)
     
    unique_append(container,value); // L'utilisateur donne un truc qui contient des caractères et un entier, "c'est pas très logique" (mais cela ne provoque pas d'erreur en C++)
    Après la fonction unique_append a pas mal de limitations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<class Container, class Value>
    void unique_append( Container& c, const Value& v ) {
        if( find(std::begin(c), std::end(c), v) == std::end(c) ) // std::begin et std::end fonctionnent pour les T []  mais pas les T *
            c.emplace_back(v);  // Tous les containeurs n'ont pas la méthode .emplace_back (std::string par exemple)
        assert( !c.empty() ); // La méthode .empty() doit exister
    }
    Ces limitations devraient être écrites dans la documentation.
    On pourrait les lever avec des spécialisations ou un code encore plus générique.
    On pourrait écrire une partie des ces limitations avec des static_assert (et avec les concepts dans des versions futures de C++).

    Je n'utilise pas auto lors des déclarations de variables sauf si le type apparaît clairement sur la même ligne ou qu'il s'agisse d'un retour de fonction.
    Les types sont importants en C++, auto permet d'augmenter la lisibilité du code s'il est bien utilisé, c'est-à-dire là où le type n'est pas très important et/ou où le nom de variable est suffisamment explicite.

  6. #6
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 579
    Points
    218 579
    Billets dans le blog
    120
    Par défaut
    Bien sur, dans ce cas l'utilisateur fait n'importe quoi, car je voulais un exemple qui plante.
    Sinon, le cas le plus probable, c'est qu'il fasse sa propre classe de container et qu'il oublie l'une des fonctions nécessaires utilisé dans unique_append. Mais il en reviendra au même problème, ou même pire, qui est que le message d'erreur sera totalement opaque et ne ciblera pas un problème d'implémentation, mais un problème dans la fonction qui utilise l'implémentation (du container).

    Même si vous écrivez tout ce que vous voulez dans la documentation, rien ne vous assure qu'elle sera lue, ou même comprise et vous en revenez au même point, un message d'erreur vraiment peu clair. C'est ça que je reproche, à force de cacher les types et autre, il en vient que les messages d'erreurs sont absolument illisibles
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  7. #7
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par LittleWhite Voir le message
    Même si vous écrivez tout ce que vous voulez dans la documentation, rien ne vous assure qu'elle sera lue, ou même comprise et vous en revenez au même point, un message d'erreur vraiment peu clair. C'est ça que je reproche, à force de cacher les types et autre, il en vient que les messages d'erreurs sont absolument illisibles
    Faut changer d'utilisateur / de programmeur ^^'

    La documentation est une étape minimal, ensuite on vient avec static_assert (et les concepts dans le futur).
    Ici le message d'erreur est clair :
    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
    97
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++98 -pedantic -fopenmp main.cpp -o main && ./main
     
    #include <type_traits>
    #include <algorithm>
    #include <cassert>
    #include <vector>
     
     
    template <class>
    class this_type
    {
    public:
     
    	/// is_valid type
    	using is_valid = void;
    };
     
     
    template <class T, class sfinae_valid_type = void>
    class has_empty_member_function : public std::false_type
    { };
     
    template <class T>
    class has_empty_member_function
    <
    	T,
    	typename this_type<decltype(std::declval<T>().empty())>::is_valid
    > : public std::true_type
    { };
     
     
    template <class container_t, class value_t, class sfinae_valid_type = void>
    class has_emplace_back_member_function : public std::false_type
    { };
     
    template <class container_t, class value_t>
    class has_emplace_back_member_function
    <
    	container_t, value_t,
    	typename this_type<decltype(std::declval<container_t>().emplace_back(std::declval<value_t>()))>::is_valid
    > : public std::true_type
    { };
     
     
    template <class T, class sfinae_valid_type = void>
    class is_std_beginable : public std::false_type
    { };
     
    template <class T>
    class is_std_beginable
    <
    	T,
    	typename this_type<decltype(std::begin(std::declval<T>()))>::is_valid
    > : public std::true_type
    { };
     
     
    template <class T, class sfinae_valid_type = void>
    class is_std_endable : public std::false_type
    { };
     
    template <class T>
    class is_std_endable
    <
    	T,
    	typename this_type<decltype(std::end(std::declval<T>()))>::is_valid
    > : public std::true_type
    { };
     
     
    template <class container_t, class value_t>
    void unique_append(container_t & c, value_t const & v)
    {
    	static_assert(is_std_beginable<container_t>::value, "Container must work in std::begin(container)");
    	static_assert(is_std_endable<container_t>::value, "Container must work in std::end(container)");
    	static_assert(has_emplace_back_member_function<container_t, value_t>::value, "Container must have .emplace_back(value_t) member function");
    	static_assert(has_empty_member_function<container_t>::value, "Container must have .empty() member function");
     
    	if (find(std::begin(c), std::end(c), v) == std::end(c)) { c.emplace_back(v); }
     
    	assert(!c.empty());
    }
     
    int main()
    {
    // 	std::string s = "Hello";
    // 	unique_append(s, 'a'); // error: static assertion failed: Container must have .emplace_back(value_t) member function
     
    // 	char const * const s = "Hello";
    // 	unique_append(s, 'a'); // error: static assertion failed: Container must work in std::begin(container)
     
    	std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    	unique_append(v, 5); // Ok
     
    	return 0;
    }

  8. #8
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 859
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 859
    Points : 218 579
    Points
    218 579
    Billets dans le blog
    120
    Par défaut
    J'aime beaucoup la solution même si cela fait sacrément lourd
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  9. #9
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Citation Envoyé par LittleWhite Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    main.cpp: In instantiation of ‘void unique_append(Container&, const Value&) [with Container = const char*; Value = int]’:
    main.cpp:17:34: required from here
    main.cpp:7:5: error: no matching function for call to ‘end(const char*&)
    Les messages d'erreurs ont toujours été "un peu" bordéliques en C++ dès que des templates sont impliqués, mais ils donnent quand même en général une bonne indication d'où vient le soucis.

    Sinon effectivement l'utilisation de static_assert permet d'avoir des erreurs simples et compréhensibles, mais c'est assez lourd à mettre en place.

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

Discussions similaires

  1. Les generics, hors les types collection ?
    Par jeanfr dans le forum Langage
    Réponses: 10
    Dernier message: 24/11/2008, 13h02
  2. Requete qui reprend les champs d'un formulaire, oui, mais pas tous
    Par Arttt dans le forum Requêtes et SQL.
    Réponses: 20
    Dernier message: 23/06/2008, 16h14
  3. Supprimer les insultes dans un texte oui mais...
    Par psychoBob dans le forum Langage
    Réponses: 19
    Dernier message: 16/04/2008, 15h03
  4. instructions TYPE imbriquées les unes dans les autres
    Par Beralienne dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 02/04/2008, 16h15

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