Bonjour,

le problème me semble si classique que j'imagine qu'il a déjà été rencontré de nombreuses fois, pourtant je n'en ai trouvé aucune réponse satisfaisante, ni ici (faq et posts précédents) ni ailleurs sur le web.

Je souhaite définir un patron de classe dont l'essentiel est présenté ici :

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
template<typename T>
class foo {
 
 public:
  typedef T value_type;
  typedef T *iterator;
  typedef const T *const_iterator;
  typedef T &reference;
  typedef const T &const_reference;
  typedef size_t size_type;
 
  typedef foo self;
 
  template <typename Iter_T>
  void copy(Iter_T first, Iter_T last);
 
  iterator begin();
  iterator end();
  const_iterator begin() const;
  const_iterator end() const;
  reference operator[](size_type n);
  const_reference operator[](size_type n) const;
  static size_type size();
 
  // friend operators
  friend self operator+ (self x, const self &y);
  friend self operator-  (self x, const self &y);
  friend self operator+ (self x, value_type y);
  friend self operator- (self x, value_type y);
  friend self operator* (self x, value_type y);
  friend self operator/ (self x, value_type y);
  friend self operator% (self x, value_type y);
};
Les définitions des fonctions et opérateurs membres et amis doivent être placées à l'extérieur pour des raisons de lisibilité de l'interface.

A priori, la déclaration de classe précédente est anodine et sans surprise (cf. par exemple le C++ Cookbook de chez O'Reilly qui propose une classe kvector très similaire), l'ennui c'est qu'elle ne passe la compilation, en tout cas sous g++ 3.4.3 et icc 9.0 (de Intel) disponible sur ma station de travail (Linux). Une recherche sur le web me porte à croire que la version actuelle du Comeau (considéré comme très conforme au standard) ne l'accepte pas non plus.

Tous exigent des chevrons <> après le nom des opérateurs (au passage, ces chevrons ne sont pas spécifiés dans l'exemple C.13.2 du Stroustrup sur les opérateurs amis de classes templates)

Avec g++ 3.4.3 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
./foo.h:51: warning: friend declaration `foo<T, N> operator+(foo<T, N>, const foo<T, N>&)' declares a non-template function
./foo.h:51: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
Avec icc 9.0 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
warning #1624: "foo<T, N>::self operator+(foo<T, N>::self, const foo<T, N>::self &)" declares a non-template function -- add <> to refer to a template instance
    friend self operator+ (self x, const self &y);
Qu'a cela ne tienne, rajoutons les chevrons demandés :
friend self operator+ <>(self x, const self &y);

Voici maintenant les réactions des compilateurs :
Avec g++ 3.2.3 :
cela compile

Avec g++ 3.4.3 et supérieur (au moins jusqu'à la version 4.0) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
./foo.h:51: error: declaration of `operator+' as non-function
./foo.h:51: error: expected `;' before '<' token
Avec icc 9.0 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
./foo.h(51): error: operator+ is not a template
    friend self operator+ <>(self x, const self &y);
                ^
          detected during instantiation of class "foo<Value_T, N> [with Value_T=int, N=4U]" at line 9 of "./test_foo.cpp"
Ma connaissance du standard C++ actuel étant très fragmentaire, les messages précédents me plongent dans un abime de perplexité. De plus, j'ai du mal à imaginer des bogues de compilateur, sur 2 compilateurs différents et plusieurs versions du même compilateur (inutile de poster pour suggérer cela, sauf preuves ou commentaires sérieux à l'appui).

Je recherche si possible une solution portable à ce problème.

Merci d'avance de vos interventions.