我只是在 std::visit 和 std::function 附近反弹到一些微妙的东西,这让我感到困惑。我并不孤单,但我能找到的唯一其他人做了“解决方法并继续前进”的舞蹈,这对我来说还不够:
这可能与 LWG 中的一个悬而未决的问题有关,但我认为这里正在发生一些更险恶的事情:
最小示例:
// workaround 1: don't include <variant>
#include <variant>
#include <functional>
struct Target
{
Target *next = nullptr;
};
struct Visitor
{
void operator()(const Target &tt) const { }
};
// workaround 2: concretely use 'const Visitor &' instead of 'std::function<...>'
void visit(const Target &target, const std::function<void(const Target &)> &visitor)
{
visitor(target);
if(target.next)
visit(*target.next,visitor); // workaround 3: explicitly invoke ::visit(...)
//^^^ problem: compiler is trying to resolve this as std::visit(...)
}
int main(int argc, char **argv, char **envp)
{
return 0;
}
用 g++ -std=c++17 编译,测试使用:
最终结果是编译器尝试使用 std::visit 来调用显然不是 std 的 visit(*target.next,visitor):
g++-8 -std=c++17 -o wtvariant wtvariant.cpp
In file included from sneakyvisitor.cpp:3:
/usr/include/c++/8/variant: In instantiation of ‘constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = Target&; _Variants = {const std::function<void(const Target&)>&}]’:
wtvariant.cpp:20:31: required from here
/usr/include/c++/8/variant:1385:23: error: ‘const class std::function<void(const Target&)>’ has no member named ‘valueless_by_exception’
if ((__variants.valueless_by_exception() || ...))
~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/8/variant:1390:17: error: no matching function for call to ‘get<0>(const std::function<void(const Target&)>&)’
std::get<0>(std::forward<_Variants>(__variants))...));
~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在我的实际用例中,我认为有人在我的树的标题空间中偷偷地添加了一个“使用命名空间 std”,我会变得脾气暴躁。然而,这个最小的例子展示了另外的情况。
关键问题:鉴于我没有创建或使用任何命名空间,为什么 std::visit(...) 会参与其中?
三种标记的解决方法中的任何一种都会抑制编译器错误,但我个人无法容忍我无法解决的语言故障(虽然我理解必要性,但我仍然对我必须多久洒一次感到不安'typename' 到模板中以使它们编译)。
另外值得注意的是,如果尝试不加限定地使用 std 命名空间的其他元素(例如,尝试一个裸的“cout”),编译器就会提示无法找出我所追求的“cout”,所以这并不是说变体 header 以某种方式扁平化了 std 命名空间。
最后,即使我把我的visit() 方法放在它自己的命名空间中,这个问题仍然存在:除非我显式调用my_namespace::visit(...),否则编译器真的想使用std::visit(...)。
我错过了什么?
最佳答案
参数 visitor
是 std::function
,它在命名空间 std
中,所以 argument-dependent lookup发现 visit
在命名空间 std
以及。
如果您总是想要 visit
在全局命名空间中,用 ::visit
这么说.
关于c++ - g++ std::visit 泄漏到全局命名空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62395578/