【发布时间】:2020-01-14 21:58:34
【问题描述】:
我在编译代码时遇到问题,因为它无法在模板上找到匹配的函数。我已将问题范围缩小到此示例:
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[]) { }
在 Gcc 9.10 上出现以下错误:
invalid initialization of reference of type 'bool&' from expression of type 'D::A' { read(n, value, _Tp()); }
在 Visual Studio 2019 上:
Error C2664 'void cv::read(const cv::FileNode &,bool &,bool)': cannot convert argument 2 from '_Tp' to 'bool &'
我发现以下任何更改都会使代码编译:
-
class A->class A : public K - 删除
read对bool的专门化 - 删除
cv命名空间 - 将
read模板移入命名空间D
不幸的是,之前的修复都不适用于我原来的问题,我仍然没有真正理解为什么它无法找到 read 模板。
【问题讨论】:
-
更改申报顺序可能会有所帮助:godbolt.org/z/ibe9DI
-
有趣的是,该更改修复了 GCC 9.10 但不修复 Visual Studio。
-
为什么你认为
read模板应该被发现?它出现在调用者之后,并且不在调用的任何关联类型的命名空间中。 -
如果我们删除
read(const FileNode& node, bool& value, bool default_value),它就能找到它,所以我希望它在该功能存在时也能工作 -
以下划线和大写字母开头的标识符,如
_Tp,为标准库保留,禁止用户代码使用。
标签: c++ templates namespaces argument-dependent-lookup