ich gerade lief in einige interessante Verhalten mit dem Argument abhängigen Lookup verhalten, die ich nicht ganz verstehen:Argument-dependent Nachschlag unerwartet auf Typen aliased aus einem anderen Namespace
#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;
}
ich, dass c::Foo
tatsächlich b::Baz<...>
ist, also macht es etwas Sinn, dass ADL den Operator findet, wenn ich ihn innerhalb namespace b
definiere. Aber es scheint der Intuition zu widersprechen, dass das Definieren des Operators innerhalb von namespace c
nicht funktioniert, da c::Foo
(IMHO) dem Compiler erlauben sollte, ADL innerhalb namespace c
auch durchzuführen.
Warum ist das nicht der Fall? Was ist der Grund dafür?
@mindriot: „* Aber das scheint wie eine Implementierung Detail *“ Nein, ist es nicht. * Nirgendwo * in C++ dürfen Sie einen Typ-Alias so verwenden, dass er sich anders verhält, als wenn Sie den tatsächlichen Typ verwendet hätten. Das ist kein "Implementierungsdetail"; das ist erforderlich für Typaliase. –
@ NicolBolas Ich stimme zu, aber das ist nicht, was ich meinte. Vielleicht sollte ich anders formulieren: Diese spezielle _explanation_ ("stelle dir vor, dass die Referenz neu geschrieben wird") lässt es klingen, als wäre es nur ein Implementierungsdetail. Der Grund, den Columbo in seiner Antwort gab, macht mehr Sinn. – mindriot