MSVC - 在通用 lambda 的调用者中使用命名空间指令泄漏到 lambda 的主体中
MSVC - Using namespace directive in caller of generic lambda leaks into the lambda's body
考虑以下玩具代码:
#include <boost/hana/transform.hpp>
#include <range/v3/view/transform.hpp>
auto constexpr f = [](auto) {
using namespace ranges::views;
auto xxx = transform;
};
void caller() {
using boost::hana::transform;
f(1);
}
它用 GCC 和 MS 的编译器编译得很好,这意味着 using boost::hana::transform;
不会影响 f
主体中可用的名称,因此 xxx
是 ranges::views::transform
.
另一方面,如果我将 using boost::hana::transform;
更改为 using namespace boost::hana;
,则 Visual Studio 声称 f
正文中的 transform
是模棱两可的名字.
这是 GCC 中的错误还是 Visual Studio?这是一个已知的错误吗?这是因为什么?
这是一个小例子 (run it):
#include <boost/hana/transform.hpp>
#include <range/v3/view/transform.hpp>
auto constexpr f = [](auto) {
using namespace ranges::views;
auto xxx = transform;
};
void caller() {
#if 1
using namespace boost::hana;
#else
using boost::hana::transform;
#endif
f(1);
}
这是一个 MSVC 错误,与 generic lambdas 有关。一个最小的例子是
void foo() {}
namespace B {
void foo() {}
}
auto moo = [](auto) {
foo();
};
int main() {
using namespace B;
moo(1);
}
它使用 c++17 和 c++20 设置重现。
已知 MSVC 对模板实例化和两阶段名称查找的处理不一致。许多这些错误在最新版本的编译器中得到修复,但显然不是全部。这里,在实例化 moo
之后,名称 foo
显然是在实例化上下文中查找的。这不应该发生,因为它不是从属名称。
相关示例:
#include <iostream>
namespace A{
template <typename K>
int foo(K) { return 1; }
}
using namespace A;
namespace B {
struct BB {};
}
auto moo = [](auto i) {
return foo(i);
};
void test1() {
std::cout << moo(B::BB{}); // Comment this and see how the output changes
}
namespace B {
int foo(BB) { return 2; }
}
void test2() {
std::cout << moo(B::BB{});
}
int main() {
test1();
test2();
}
(查看 here 的实际效果。)
考虑以下玩具代码:
#include <boost/hana/transform.hpp>
#include <range/v3/view/transform.hpp>
auto constexpr f = [](auto) {
using namespace ranges::views;
auto xxx = transform;
};
void caller() {
using boost::hana::transform;
f(1);
}
它用 GCC 和 MS 的编译器编译得很好,这意味着 using boost::hana::transform;
不会影响 f
主体中可用的名称,因此 xxx
是 ranges::views::transform
.
另一方面,如果我将 using boost::hana::transform;
更改为 using namespace boost::hana;
,则 Visual Studio 声称 f
正文中的 transform
是模棱两可的名字.
这是 GCC 中的错误还是 Visual Studio?这是一个已知的错误吗?这是因为什么?
这是一个小例子 (run it):
#include <boost/hana/transform.hpp>
#include <range/v3/view/transform.hpp>
auto constexpr f = [](auto) {
using namespace ranges::views;
auto xxx = transform;
};
void caller() {
#if 1
using namespace boost::hana;
#else
using boost::hana::transform;
#endif
f(1);
}
这是一个 MSVC 错误,与 generic lambdas 有关。一个最小的例子是
void foo() {}
namespace B {
void foo() {}
}
auto moo = [](auto) {
foo();
};
int main() {
using namespace B;
moo(1);
}
它使用 c++17 和 c++20 设置重现。
已知 MSVC 对模板实例化和两阶段名称查找的处理不一致。许多这些错误在最新版本的编译器中得到修复,但显然不是全部。这里,在实例化 moo
之后,名称 foo
显然是在实例化上下文中查找的。这不应该发生,因为它不是从属名称。
相关示例:
#include <iostream>
namespace A{
template <typename K>
int foo(K) { return 1; }
}
using namespace A;
namespace B {
struct BB {};
}
auto moo = [](auto i) {
return foo(i);
};
void test1() {
std::cout << moo(B::BB{}); // Comment this and see how the output changes
}
namespace B {
int foo(BB) { return 2; }
}
void test2() {
std::cout << moo(B::BB{});
}
int main() {
test1();
test2();
}
(查看 here 的实际效果。)