2017-06-10 9 views
10

打ち鳴らすの以下のdoesn't compileに関連打ち鳴らすのバグ++であると考えている:私はこれがクラスのパブリックメンバ関数へのアクセス

#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

あなたのリンクはすべて言った:* "あなたは 'S :: p'を意味しましたか?" * –

+5

コンパイラのエラーを質問に貼り付けてください。 – aschepler

+4

変換演算子の名前ルックアップでは、字句(文字)マッチングではなくタイプマッチングが使用されます。 's.operator decltype(&f)()()' –

答えて

17

これはClangのバグです。私はコードが正しいと信じています。

クラン4.0.0レポート:

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

しかし、C++ 14 3.4.5/7 [basic.lookup.classref]

からID-発現は、変換の場合-function-idの場合、変換式IDは オブジェクト式のクラスで最初に検索され、名前が見つかった場合はその名前が使用されます。それ以外の場合は、 postfix-expression全体のコンテキストで検索されます。これらのルックアップのそれぞれには、特殊化タイプが のタイプまたはテンプレートを示す名前のみが考慮されます。

[例:

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は資格を必要とすることなくクラスで発見されているべきです。

+0

さらなる分析の後、私は本当にその理由を理解しているとは思わない[basic.lookup.classref]/7のpostfix-expression全体のコンテキストで検索されます。 [ここ](http://coliru.stacked-crooked.com/a/2f827434ffe43e3b)の例はコンパイルできないことに注意してください。上記の文章がどのような用途に使用されるかを例を挙げて教えてください。 – Alexander

+0

この例では、型名 'A'は' N :: A'を意味する '-N :: A'のコンテキストで正しく検索されます。アクセスされたオブジェクトにそのような演算子がないという事実は、別のエラーです。 – aschepler

+0

ここでは、クラス型のスコープ内で名前の参照が失敗する例を示しますが、postfix-expression全体のスコープ内で名前の参照が成功します:http://coliru.stacked-crooked.com/a/8fa9ae6e5f261edc ' b。演算子A(); 'は、' N :: B'のスコープから名前がAではありませんが、 'M :: A'を呼び出すスコープから' M :: A'を見つけることができます。 – aschepler

関連する問題