gpt4 book ai didi

c++ - 定制点 - 命名空间注入(inject)

转载 作者:行者123 更新时间:2023-11-30 05:06:06 30 4
gpt4 key购买 nike

首先是冗长的解释,其次是实际问题:

在 C++ 库中,我想提供自定义点。也就是说,某些方法可以由用户“注入(inject)”。通常,这是通过 ADL 以下列方式完成的:

文件 operators.h 包含:

namespace operators
{
namespace print_overloads
{
void print_value(double x)
{
cout << x << endl;
}
}

namespace detail
{
template <typename Value>
void adl_print(Value x)
{
using print_overloads::print_value;
print_value(x);
}
}

template <typename Value>
void print(Value x)
{
detail::adl_print(x);
}
}

print_value() 通过 ADL 提供定制点。要使用它,可能需要在 testi.cpp 中:

#include "operator.h"
namespace custom
{
struct A {};

void print_value(A)
{
cout << "ADL A overload" << endl;
}
}


int main()
{
operators::print(custom::A{});
}

这按预期工作。但是,它仅适用于用户可以在相应命名空间(在本例中为 namespace custom)定义函数的情况。

我的想法是在上面的例子中引入一个专用的重载命名空间,namespace print_overload。对于用户,这应该允许:

#include "operators.h"
namespace custom_inaccessible
{
struct A {};
}

namespace operators::print_overloads
{
void print_value(custom_inaccessible::A)
{
cout << "A overload" << endl;
}
}


int main()
{
operators::print(custom_inaccessible::A{});

int pause;
std::cin >> pause;
return 0;
}

不幸的是,这不起作用。当前的 Microsoft Visual Studio 2017 C++ 编译器失败并显示:

错误 C2664:“void operators::print_overloads::print_value(double)”:无法将参数 1 从“testi::B”转换为“double”

看来,print_value(A) 的重载未在重载列表中考虑。经过一些修补,我发现一致性模式设置设置为 Yes(/permissive-)。如果我将其设置为 No,一切正常。

现在回答问题:

  • 标准中定义了这种行为吗?
  • 如果是,标准的哪一部分导致了这个结果?
  • 还是 Visual Studio 一致性模式存在一些错误?

最佳答案

要回答您对标准的查询,相关段落位于 [temp.dep.candidate] :

For a function call where the postfix-expression is a dependent name, the candidate functions are found using the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) except that:

  • For the part of the lookup using unqualified name lookup, only function declarations from the template definition context are found.
  • For the part of the lookup using associated namespaces ([basic.lookup.argdep]), only function declarations found in either the template definition context or the template instantiation context are found.

上面的意思是,由于 using print_overloads::print_value;(根据第一个项目符号,不合格的名称查找)而找到的任何内容都必须在定义模板时已经存在.用户不能只是重新打开命名空间然后再添加它。

MSVC 以一致性模式拒绝它是非常正确的。


具体来说,根据[namespace.udecl]/1,using 声明通过限定名称查找引入名称。 :

Each using-declarator in a using-declaration introduces a set of declarations into the declarative region in which the using-declaration appears. The set of declarations introduced by the using-declarator is found by performing qualified name lookup for the name in the using-declarator, excluding functions that are hidden as described below.

但是,using 声明只是引入非依赖名称。并根据[temp.nondep]/1 :

Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used.

“使用它们的点”是模板定义的点。

关于c++ - 定制点 - 命名空间注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48096617/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com