2017-06-10 36 views
10

Poniższe doesn't compile w brzękiem:Wierzę, że jest to błąd w brzękiem ++ związane z dostępem do funkcji składowej publicznej klasy za

#include <iostream> 

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

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

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

Plony:

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

Ale to powinno , ponieważ wyrażenie s.operator p()() uzyskuje dostęp do publicznej funkcji składowej obiektu S::s. Czy czegoś brakuje?

Jeśli się mylę, byłbym wdzięczny za wycenę ze Standardu, który wspierałby odpowiedź.

+1

Twój link powiedział wszystko: * "czy miałeś na myśli" S :: p "?" * –

+5

Proszę wkleić błędy kompilatora do pytania, nie tylko link do nich. – aschepler

+4

Wyszukiwanie nazw dla operatorów konwersji używa dopasowywania typów zamiast dopasowywania leksykalnego (znakowego). Szukanie powiodłoby się, nawet gdybyś powiedział: 's.operator decltype (& f)()()' –

Odpowiedz

17

Wygląda na to, że jest to błąd w Clangu. Uważam, że kod jest poprawny.

Clang 4.0.0 raporty:

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

Jednak z C++ 14 3.4.5/7 [basic.lookup.classref]

Jeśli identyfikator ekspresja jest konwersja -function-id, jego identyfikator typu-konwersji jest najpierw wyszukiwany w klasie wyrażenia obiektowego i używana jest nazwa, jeśli została znaleziona. W przeciwnym razie jest on sprawdzany w kontekście całego wyrażenia Postfiksa. W każdym z tych wyszukiwań brane są pod uwagę tylko te nazwy, które oznaczają typy lub szablony, których specjalizacje są typami .

[przykład:

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 
} 

- przykład end]

W przykładzie typ p powinny zostać znalezione w klasie nie wymaga kwalifikacji.

+0

Po dalszej analizie nie sądzę, żebym naprawdę rozumiał przyczynę zdania "W przeciwnym razie jest wyeksponowany w kontekście całego wyrażenia Postfix "w [basic.lookup.classref]/7. Zauważ, że przykład pokazany [tutaj] (http://coliru.stacked-crooked.com/a/2f827434ffe43e3b) nie może się skompilować. Czy mógłbyś pokazać przykład, w którym powyższe zdanie byłoby przydatne? – Alexander

+0

W tym przykładzie nazwa typu "A" jest prawidłowo sprawdzana w kontekście "N :: A", podając nazwę klasy wtryskiwanej, co oznacza "N :: A". Fakt, że nie masz żadnego takiego operatora w dostępnym obiekcie, jest oddzielnym błędem. – aschepler

+0

Oto przykład, w którym wyszukiwanie nazwy w zakresie typu klasy nie powiedzie się, ale wyszukiwanie nazwy w zakresie całego wyniku postfixa się powiedzie: http://coliru.stacked-crooked.com/a/8fa9ae6e5f261edc W wywołaniu ' b.operator A(); ', nie ma nazwy' A' z zakresu 'N :: B', ale' M :: A' można znaleźć z zakresu wywołania funkcji 'M :: f'. – aschepler