Ho appena incontrato alcuni comportamenti interessanti con la ricerca argomento-dipendente, che non capiscono fino in fondo:ricerca Argument-dependent comportarsi in modo imprevisto sui tipi alias da un altro spazio dei nomi
#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;
}
ottengo che c::Foo
è in realtà b::Baz<...>
, quindi in qualche modo ha senso che ADL trovi l'operatore quando lo definisco all'interno di namespace b
. Ma sembra sfidare l'intuizione che la definizione dell'operatore all'interno di namespace c
non funzioni, poiché c::Foo
dovrebbe (IMHO) consentire al compilatore di eseguire ADL anche all'interno di namespace c
.
Perché non è così? Qual è la logica alla base di questo?
@mindriot: "* Ma che sembra come un dettaglio di implementazione *" No, non lo è. * In nessun luogo * in C++ è possibile utilizzare un alias di tipo in un modo che si comporterebbe in un modo diverso rispetto a quando si è utilizzato il tipo effettivo. Questo non è un "dettaglio di implementazione"; questo è il comportamento richiesto per i tipi di alias. –
@NicolBolas Sono d'accordo, ma non è quello che intendevo. Forse dovrei riformulare: Quella particolare _esplanation_ ("immagina che il riferimento venga riscritto") fa sembrare che sia solo un dettaglio di implementazione. La ragione per cui Columbo ha dato nella sua risposta ha più senso. – mindriot