1

Should name resolution work for A, B, C in the following code in parameter list of f definition?

namespace ns
{
struct A {};
struct S
{
    struct B {};
    struct
    {
        struct C {};
        void f(A, B, C);
    } x;
};
}

#include <type_traits>

void std::type_identity_t<decltype(ns::S::x)>::f(A, B, C) {}

int main()
{
}

Actually it works in latest clang.

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169

1 Answers1

2

[basic.lookup.unqual]/8 For the members of a class X, a name used ... in the definition of a class member outside of the definition of X, following the member's declarator-id(24), shall be declared in one of the following ways:
...
(8.2) — shall be a member of class X ..., or
(8.3) — if X is a nested class of class Y (11.4.10), shall be a member of Y,... or
...
(8.5) — if X is a member of namespace N, or is a nested class of a class that is a member of N, ... before the use of the name, in namespace N or in one of N's enclosing namespaces.

Footnote 24) That is, an unqualified name that occurs, for instance, in a type in the parameter-declaration-clause or in the noexcept-specifier.

Here X is decltype(ns::S::x), Y is S, N is ns. Therefore, A is found via (8.5), B via (8.3), C via (8.2).

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • But `std::type_identity_t` is not a class (`X`). It is a specialization of alias template. – Tomilov Anatoliy Nov 09 '20 at 19:20
  • It's a `using` alias that names a class. It doesn't matter how `X` is referred to - whether by its original name, or typedef, or `using` alias, or `decltype`, or otherwise. – Igor Tandetnik Nov 09 '20 at 23:39