Strange compilation error regarding overload resolution

This piece of code:

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

gives the following error on Comeau and a very similar error on 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

It compiles, however, if the before is #1given either #2, or if lastdeclared out ns.

Any explanation for this?

+3
source share
2 answers

Case 1)

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

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

You need to make sure that it #2is a specialized template #1by specifying template<>abovevoid f(const chain<last>&) // #2

Without template<> void f(const chain<last>&)will be interpreted as overload f. Therefore, the call f(x.next);will be poorly formed due to the missing announcement 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!!
}
+3

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> , chain<last> next.

, , -, last , . ? . .

hth.,

0

Source: https://habr.com/ru/post/1770150/


All Articles