C++ 定制点-名称空间注入
首先是冗长的解释,其次是实际问题:C++ 定制点-名称空间注入,c++,visual-studio-2017,overloading,C++,Visual Studio 2017,Overloading,首先是冗长的解释,其次是实际问题: 在C++库中,我想提供定制点。也就是说,用户可以“注入”某些方法。通常,这是通过ADL以以下方式完成的: 文件operators.h包含: namespace operators { namespace print_overloads { void print_value(double x) { cout << x << endl; } }
在C++库中,我想提供定制点。也就是说,用户可以“注入”某些方法。通常,这是通过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);
}
}
这正是我们想要的。但是,仅当用户可以在相应的命名空间中定义函数时(在本例中为namespace custom
)
我的想法是在上面的示例中引入一个专用的重载名称空间,namespace print\u-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;
}
#包括“operators.h”
命名空间自定义\u不可访问
{
结构A{};
}
名称空间运算符::print_重载
{
无效打印值(自定义打印不可访问::A)
{
不能停顿;
返回0;
}
遗憾的是,这不起作用。当前微软Visual Studio 2017 C++编译器失败了:
错误C2664:'void运算符::print_重载::print_值(double)':无法将参数1从'testi::B'转换为'double'
似乎,print\u value(A)
的重载没有被考虑在重载列表中。经过一些修补,我发现一致性模式设置设置设置为Yes(/permissive-
。如果我将其设置为No
,一切正常
现在回答问题:
- 该行为是否在标准中定义
- 如果是,标准的哪一部分对该结果负责
- 或者它是VisualStudio一致性模式的一些bug
- 对于使用非限定名称查找的查找部分,只找到模板定义上下文中的函数声明
- 对于使用关联名称空间([basic.lookup.argdep])的查找部分,在 模板定义上下文或模板实例化上下文 找到了
为了详细说明,using声明通过限定名称查找引入名称,根据: using声明中的每个using声明符都引入了一组 声明进入声明性区域,其中 将显示using声明。由 通过对 使用声明器中的名称,不包括隐藏为 如下所述 但是,using声明只引入了非依赖名称。根据: 模板定义中使用的非依赖名称可以使用 通常的名称查找和使用点的绑定
“使用点”作为模板定义的要点。尝试gcc和clang的代码。但看起来一致性模式设置的行为正确,不一致性模式不正确,因为在解析函数调用时只考虑以前声明的函数,MSVC直到最近才对模板出错。I我会说使用ADL做这件事是很不寻常的。最好引入一些用户可以专门化的类型特征,或者接受一些带有默认值的额外模板参数。@VTT我指的是:我看不出
使用print\u重载::print\u value;
是一种不合格的名称查找。根据,“对于非限定名称,即不显示在作用域解析运算符右侧的名称::”,这应该是限定名称查找?@LcdDrm-print_value(x);
是非限定名称查找(对于print_value
)。必须事先声明使用声明提供给它的名称。
#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;
}