astrid <wang_a(a)epita.fr> writes:
astrid <wang_a(a)epita.fr> writes:
Bon, j'ai un bout de code :
-------------------------------------------------------
#include <iostream>
#include <oln/basics2d.hh>
namespace oln {
namespace foo {
template <class I>
struct A
{
A(const typename I::point_type& p) : p(p) {}
typename I::point_type p;
};
template <class I>
std::ostream&
operator<<(std::ostream& os, const A<I>& a)
{
os << a.p << std::endl; // KO
// operator<<(os, a.p) << std::endl; // KO
// ::operator<<(os, a.p) << std::endl; // OK
return os;
}
} // foo
} // oln
using namespace oln;
using namespace foo;
using namespace ntg;
int main()
{
const A<image2d<int_u8> >& a(point2d(7,13));
std::cout << a << std::endl;
}
-------------------------------------------------------
Je compile avec g++-3.2
g++-3.2 -I ../olena -I ../integre -I ../metalic pouet.cc -o pouet
pouet.cc: In function `std::ostream& oln::foo::operator<<(std::ostream&,
const
oln::foo::A<I>&) [with I = oln::image2d<ntg::int_u8, mlc::final>]':
pouet.cc:42: instantiated from here
pouet.cc:23: no match for `std::basic_ostream<char, std::char_traits<char>
>&
<< const oln::point2d&' operator
/usr/include/c++/3.2/bits/ostream.tcc:55: candidates are: [... plein de
gens qui n'ont rien a voir ...]
etc.
:(
Je viens de dépiler cette histoire :)
Bon, après investigation, c'est tout à fait normal. Comme d'hab avec
le C++, c'est assez tordu. Récapitulation des règles de lookup en c++
pour une configuration du style :
namespace n1 {
void bar(char*);
namespace n2 {
void bar(int);
void foo() {
bar("mystring");
}
//...
}
}
On cherche "bar". L'ensemble des règles pour constituer l'ensemble des
"bar" possibles sont :
- Dépiler les namespaces supérieurs jusqu'à ce qu'on trouve 1 symbole
nommé "bar". Si on en trouve 1, chercher toutes les occurences de
"bar" dans ce scope, et s'arrêter (on ne va pas dans les namespaces
encore plus hauts). Ici, on va trouver un "bar" dans n2 donc on
s'arrete à n2. Seul bar(int) sera donc proposé par cette règle.
- Regarder dans les namespaces des arguments de la fonction, ici dans
le namespace de "mystring", donc rien.
Ensuite l'ensemble des "bar" trouvé est soumis aux règles de
l'overloading.
Dans cet exemple, bar(char*) ne sera pas analysé.
Il se passe la même chose avec nos points :
- Dans oln::foo::operator<< , l'appel à operator<< cherche d'abord
dans oln::foo, et trouve un operator<< (lui meme en l'occurence). Du
coup il s'arrete et ne cherche pas plus loin.
- Il regarde aussi dans le namespace de l'argument (a.p), et va donc
voir dans oln::. Il n'y trouve rien.
En aucun cas il n'a eu à aller voir dans le scope global ::.
Solutions :
- Mettre les operator<< dans le meme namespace que le type concerné
(ici oln:: pour point2d)
- Mettre _tous_ les operator<< dans le namespace global ::