C++ C++;奇怪的模板/名称空间行为
我在编译代码时遇到问题,因为它无法在模板上找到匹配的函数。我已将问题缩小到以下示例:C++ C++;奇怪的模板/名称空间行为,c++,templates,namespaces,argument-dependent-lookup,C++,Templates,Namespaces,Argument Dependent Lookup,我在编译代码时遇到问题,因为它无法在模板上找到匹配的函数。我已将问题缩小到以下示例: namespace cv { class FileNode { }; template<typename _Tp> static inline void operator >> (const FileNode& n, _Tp& value) { read(n, value, _Tp()); } stati
namespace cv
{
class FileNode
{ };
template<typename _Tp> static inline void operator >> (const FileNode& n, _Tp& value)
{
read(n, value, _Tp());
}
static inline void read(const FileNode& node, bool& value, bool default_value)
{ }
}
class K
{ };
namespace D
{
class A
{ };
}
template<class X>
static void read(const cv::FileNode& node, X& x, const X& default_value)
{
return;
}
using namespace D;
class B
{
void read(const cv::FileNode& fn)
{
A a;
fn >> a;
}
};
int main(int argc, char* argv[]) { }
关于Visual Studio 2019:
错误C2664'void cv::read(const cv::FileNode&,bool&,bool)':无法将参数2从'\u Tp'转换为'bool&'
我发现以下任何更改都会导致代码编译:
->A类
A类:公共K
- 删除
专门化read
bool
- 删除
命名空间cv
- 将
模板移动到命名空间read
D
读取模板。ADL回击:
在
模板静态内联无效运算符>>(const FileNode&n、\u Tp&value)
{
读取(n,值,_-Tp());
}
read
未声明,因此只能通过
因此,它将在与FileNode
(Socv
)相关联的名称空间中搜索,并搜索与\u Tp
相关联的名称空间
当\u Tp
是D::A
时,它将是命名空间D
而read
唯一可能的过载是cv::read
,它需要bool
将read
的声明移动到上面cv::operator>
解决问题也将与ADL一起考虑
通常,我会将类和名称空间分离到不同的.hpp文件中,这会自动迫使您执行以下功能:
template<typename _Tp> static inline void operator >> (const FileNode& n, _Tp& value)
模板静态内联无效运算符>>(const FileNode&n、\u Tp&value)
在使用它的名称空间之前声明(如cv
)
我认为避免此类问题的最佳方法是清理代码,并尽可能使其独立。这样,每当您想在另一个名称空间中使用此独特的read
函数时,您就不需要将新名称空间放在该文件中,也不需要包含该文件中当前的所有名称空间。更改声明顺序可能会有帮助:有趣,这一更改修复了GCC 9.10,但没有修复Visual Studio。为什么您认为应该找到read
模板?它出现在调用方之后,不在调用的任何关联类型的命名空间中。如果我们删除read(const FileNode&node,bool&value,bool default\u value)
,它就能够找到它,因此我希望它在该函数是以下划线和大写字母开头的标识符时也能工作,如\u Tp
,为标准库保留,用户代码禁止使用。
template<typename _Tp> static inline void operator >> (const FileNode& n, _Tp& value)