Я считаю, что это ошибка в clang++, связанная с доступом к функции открытого члена класса

Следующий не компилирует в clang:

#include <iostream>

void f() { std::cout << "f()\n"; }

struct S {
    typedef void(*p)();
    operator p() { return f; }
};

int main()
{
    S s;
    s.operator p()();
}

Урожайность:

main.cpp:13:16: error: unknown type name 'p'; did you mean 'S::p'?
    s.operator p()();
               ^
               S::p

main.cpp:6:19: note: 'S::p' declared here
    typedef void(*p)();
                  ^

Но он должен, поскольку выражение s.operator p()() обращается к публичной функции-члену объекта S::s. Я что-то пропустил?

Если я ошибаюсь, я был бы признателен за цитату из стандарта, поддерживающего ответ.

Ответ 1

Это похоже на ошибку в Clang. Я считаю, что код правильный.

Отчеты Clang 4.0.0:

<source>:13:16: error: unknown type name 'p'; did you mean 'S::p'?
    s.operator p()();
           ^

Однако из С++ 14 3.4.5/7 [basic.lookup.classref]

Если id-выражение является идентификатором функции-преобразования, его идентификатор типа преобразования сначала просматривается в классе выражение объекта и имя, если найдено, используется. В противном случае он рассматривается в контексте всего постфикс-выражение. В каждом из этих поисков используются только имена, обозначающие типы или шаблоны, специализации рассматриваются типы.

[Пример:

struct A { };
namespace N {
struct A {
    void g() { }
    template <class T> operator T();
};
}


int main() {
    N::A a;
    a.operator A();
       // calls N::A::operator N::A
}

- конец примера]

В вашем примере тип p должен был быть найден в классе, не требуя квалификации.