2016-03-07 25 views
17

次は、両方のコンパイラでエラーが関数を返す関数の宣言の違法を扱うgccと打ち鳴らす関数を返す関数型を記述できますか?

#include <type_traits> 

int foo(); 

int main() 
{ 
    using R = std::result_of_t<decltype(foo)()>; // error 
} 

の両方でコンパイルに失敗します。しかし、私はそのような関数を宣言していません - 私はその型を書くことを試みています - それはresult_ofが期待しているからです。これは実際にはまだ貧弱ですか?

+8

私はこの "両方のコンパイラでのエラーは、関数を返す関数の宣言の違法性を扱っていると思います。"実際にはエラー – Guiroux

+4

で置き換えられます。なぜ 'decltype(foo())'を使わないのですか? – StenSoft

+3

関数が別の関数型を返す関数型を作成することはできません。 "関数は戻り値の型が 型の配列または関数ではありません" dcl.fct/8 – Simple

答えて

10

あなたは文法的に[...]エンティティの名前を省略し、その型の変数や関数の宣言を

として [dcl.name]に定義されている タイプ-IDを渡しています。 [...] アブストラクト宣言子の中の場所を一意的に識別することができます。この場合、宣言で宣言子が宣言された場合、識別子は となります。次に、指定された型は、 仮想識別子の型と同じです。

仮説識別子がある種の型を持つためには、仮説宣言が最初に正しい形式でなければなりません。しかしそれは[dcl.fct]/10によるものではありません。したがって、プログラムは不正な形式です(コンパイラのエラーメッセージは実際には分かりやすい)。このケースも[temp.deduct]/(8.10)でより直接的にカバーされており、これは(SFINAEに優しい)エラーであることを示しています。


実際、無効なタイプの使用を暗示するだけでは、プログラムを不正なものにするには十分です。例えば。機能を返す機能させるタイプのポインタを作成することは悪い形成されている:

using f = int(); 
using t = f(*)(); 

だから、次のとおりです。

struct A {virtual void f() = 0;}; 
using t = A(*)(); 

(クランは、このCfのGCCのバグ17232の興味深い議論を受け入れるべきではありません。) 。

+1

私はこのeel.is事が本当に好きです。 – Barry

関連する問題