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).