3

此代码片段:

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

在 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

但是,如果在#2. 之前定义#1或者lastns.

对此有何解释?

4

2 回答 2

3

情况1)

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

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

您需要通过上面指定来确保这#2是模板专业化#1template<>void f(const chain<last>&) // #2

没有template<> void f(const chain<last>&)将被解释为f. 因此,f(x.next);由于缺少void f(const chain<last>&).

在函数模板上方添加重载声明将使您的代码编译。

解决方案:

1)

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

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

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
{
}

案例2)

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

template <typename T>
void f(const T& x)          // #1
{
    f(x.next); // found!!
}
于 2010-10-18T17:14:13.133 回答
0

给定

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

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

...第f一个体内的调用永远不能调用第二个f,因为此时第二个f是不可见的。

因此,如果您进入第一个f,那么它将递归到第一个错误。:-) 我在这里谈论的是编译时递归,只要是尚未实例化next的类型。f

和电话main,...

int main()
{
    f(chain<first>());
}

... 必须调用第一个f,因为chain<first>与第二个的参数类型不匹配f

这导致f(类型为 arg 的递归调用chain<last> )。当尝试实例化f参数类型时,您会收到错误,chain<last>因为next.chain<last>

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

干杯&hth.,

于 2010-10-18T20:03:09.433 回答