Je viens de croiser un comportement intéressant avec recherche dépendante argument, que je ne comprends pas bien:recherche dépendant de l'argument se comportant de façon inattendue sur les types crénelage d'un autre espace de noms
#include <iostream>
namespace a {
struct Foo {
Foo(int v1, int v2) : v1(v1), v2(v2) { }
int v1,v2;
};
}
namespace b {
template <typename T>
struct Baz : T {
using T::T;
};
}
namespace c {
using Foo = ::b::Baz< ::a::Foo>;
// (1) NOT FOUND BY ADL
// std::ostream& operator << (std::ostream& os, const Foo& foo)
// {
// return os << foo.v1 << "," << foo.v2;
// }
}
namespace b {
// (2) FOUND BY ADL
std::ostream& operator << (std::ostream& os, const ::c::Foo& foo)
{
return os << foo.v1 << "," << foo.v2;
}
}
int main()
{
c::Foo foo(1,2);
// Variant (1): ADL fails: should it not find
// c::operator<<(std::ostream&, const Foo&) ?
// Variant (2) compiles
std::cout << "foo: " << foo << std::endl;
}
Je reçois que c::Foo
est en fait b::Baz<...>
, il est donc logique que ADL trouve l'opérateur lorsque je le définis à l'intérieur namespace b
. Mais il semble défier l'intuition que la définition de l'opérateur à l'intérieur namespace c
ne fonctionne pas, puisque c::Foo
devrait (IMHO) permettre au compilateur d'effectuer ADL à l'intérieur de namespace c
ainsi.
Pourquoi cela n'est-il pas le cas? Quelle est la logique derrière cela?
@mindriot: «Mais cela semble être un détail de mise en œuvre * » Non, ça ne l'est pas. * Nulle part * en C++ vous êtes autorisé à utiliser un alias de type d'une manière qui se comporterait d'une manière différente que si vous utilisiez le type réel. Ce n'est pas un "détail d'implémentation"; c'est le comportement requis pour les alias de type. –
@NicolBolas Je suis d'accord, mais ce n'est pas ce que je voulais dire. Peut-être que je devrais reformuler: Cette _explanation_ particulière ("imagine la référence à réécrire") donne l'impression que c'est juste un détail d'implémentation. La raison que Columbo a donnée dans sa réponse a plus de sens. – mindriot