依赖于参数的查找在从另一个名称空间别名的类型上出现意外行为
Argument-dependent lookup behaving unexpectedly on types aliased from another 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;
}
我知道 c::Foo
实际上是 b::Baz<...>
,所以当我在 namespace b
中定义它时,ADL 找到运算符有点有意义。但这似乎违背了直觉,即在 namespace c
内定义运算符不起作用,因为 c::Foo
应该 (恕我直言)允许编译器在 [=14 内执行 ADL =] 还有。
为什么不是这样?这背后的原理是什么?
Typedef names and using-declarations used to specify the types do not
contribute to this set.
typedef 名称和 using 声明都不隶属于它们指定的类型。如果它们是(这实际上是违反直觉的,IMO),事情就会很容易崩溃;仅仅因为我对一些 class 进行了类型定义,所有调用现在都在考虑在 typedef 附近添加的函数,这实际上是不需要的:
#include <string>
namespace A {
using str = std::string;
int stoi(str); // This will be a candidate in e.g. stoi(std::string{"0.4"}),
// leading to potentially different behavior or ambiguity
namespace B {
int stoi(std::string); // This is no candidate, because...?
}
我只是 运行 使用参数相关查找的一些有趣行为,我不完全理解:
#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;
}
我知道 c::Foo
实际上是 b::Baz<...>
,所以当我在 namespace b
中定义它时,ADL 找到运算符有点有意义。但这似乎违背了直觉,即在 namespace c
内定义运算符不起作用,因为 c::Foo
应该 (恕我直言)允许编译器在 [=14 内执行 ADL =] 还有。
为什么不是这样?这背后的原理是什么?
Typedef names and using-declarations used to specify the types do not contribute to this set.
typedef 名称和 using 声明都不隶属于它们指定的类型。如果它们是(这实际上是违反直觉的,IMO),事情就会很容易崩溃;仅仅因为我对一些 class 进行了类型定义,所有调用现在都在考虑在 typedef 附近添加的函数,这实际上是不需要的:
#include <string>
namespace A {
using str = std::string;
int stoi(str); // This will be a candidate in e.g. stoi(std::string{"0.4"}),
// leading to potentially different behavior or ambiguity
namespace B {
int stoi(std::string); // This is no candidate, because...?
}