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++_Templates_Namespaces_Compiler Errors_Overload Resolution - Fatal编程技术网

C++ 关于重载解析的奇怪编译错误

C++ 关于重载解析的奇怪编译错误,c++,templates,namespaces,compiler-errors,overload-resolution,C++,Templates,Namespaces,Compiler Errors,Overload Resolution,此代码片段: namespace ns { struct last; struct first { typedef last next; }; template <typename T> struct chain { chain<typename T::next> next; }; template <> struct chain<las

此代码片段:

namespace ns
{
    struct last;

    struct first
    {
        typedef last next;
    };

    template <typename T>
    struct chain
    {
        chain<typename T::next> next;
    };

    template <>
    struct chain<last>
    {
    };
}

using namespace ns;

template <typename T>
void f(const T& x)          // #1
{
    f(x.next);
}

void f(const chain<last>&)  // #2
{
}

int main()
{
    f(chain<first>());
}
ns
{
最后构造;
结构优先
{
键入def last-next;
};
模板
结构链
{
链下;
};
模板
结构链
{
};
}
使用名称空间ns;
模板
无效f(常数T&x)/#1
{
f(x.next);
}
空f(常数链&)/#2
{
}
int main()
{
f(chain());
}
在Comeau上给出以下错误,在GCC上给出一个非常类似的错误:

"ComeauTest.c", line 27: error: class "ns::chain<ns::last>" has no member "next"
    f(x.next);
        ^
          detected during:
            instantiation of "void f(const T &) [with T=ns::chain<ns::last>]"
                      at line 27
            instantiation of "void f(const T &) [with T=ns::chain<ns::first>]"
                      at line 36
“ComeauTest.c”,第27行:错误:类“ns::chain”没有成员“next”
f(x.next);
^
在以下期间检测到:
实例化“void f(const T&)[带T=ns::chain]”
第27行
实例化“void f(const T&)[带T=ns::chain]”
第36行
但是,如果在
#1
之前定义了
#2
,或者在
ns
之外声明了
最后一个
,则它会编译

对此有何解释?

案例1)

(二)

void f(常量链&);//#0
模板
无效f(常数T&x)/#1
{
f(x.next);//嗯,我可以看到#0,调用#2
}
空f(常数链&)/#2
{
}

案例2)

void f(常量链&)/2
{
}
模板
无效f(常数T&x)/#1
{
f(x.next);//找到了!!
}
给定

template <typename T>
void f(const T& x)          // #1
{
    f(x.next);
}

void f(const chain<last>&)  // #2
{
}
。。。必须调用第一个
f
,因为
chain
与第二个
f
的参数类型不匹配

这将导致递归调用
f(
arg类型
chain
。当尝试为参数类型
chain
实例化
f
时,您会得到一个错误,因为
chain
中没有
next
属性

关于在全局名称空间中放置
last
声明时代码是否正常,我不知道。你确定吗?注意:我还没有用真正的编译器尝试过这些


干杯,

但是
#1
的POI就在
main
之后,在那里可以看到
#2
。我的困惑(可能还有uj2)是调用main中的f是选择模板化的f,而不是非模板化的f。在调用
main
时,两个函数都可见,对吗?为什么会发生这种情况?@JoshD:考虑哪些重载有复杂的规则。我的猜测是,非正式地说,如果编译器可以在定义点决定调用什么,那么它就不会在实例化点改变这个决定。
template <typename T>
void f(const T& x)          // #1
{
    f(x.next); //hmm specialized version down there.
}

template<>
void f(const chain<last>&)  // #2
{
}
void f(const chain<last>&); // #0

template <typename T>
void f(const T& x)          // #1
{
    f(x.next); //hmm I can see #0, call #2
}

void f(const chain<last>&)  // #2
{
}
void f(const chain<last>&)  // #2
{
}

template <typename T>
void f(const T& x)          // #1
{
    f(x.next); // found!!
}
template <typename T>
void f(const T& x)          // #1
{
    f(x.next);
}

void f(const chain<last>&)  // #2
{
}
int main()
{
    f(chain<first>());
}