Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;奇怪的模板/名称空间行为_C++_Templates_Namespaces_Argument Dependent Lookup - Fatal编程技术网

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
(So
cv
)相关联的名称空间中搜索,并搜索与
\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)