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>());
}