2017-10-30 20 views
20

次のコード対C++ 14には、グラムでコンパイルすることはできません++オプション-std=c++1yとバージョン5.4.0:デフォルト引数を持つ関数を間接参照 - C++ 11

void f(int=0) ; 

int main() { 
    f(); // ok 
    (*f)(2);// ok 
    (*f)();// ok c++11; error with c++14: too few arguments to function 
    return 0; 
} 

デフォルト引数を持つように宣言された関数ここで何が間違っていますか? ありがとうございました。

g++ -c -std=c++11はなぜコンパイルされますか?

+1

明らかな答えは、新しい「g ++」バージョンを試すことです。 5行は古く、5.4は最新のマイナーリリースでもありません。このような場合には、GCC Bugzillaを検索することも賢明です。問題はすでに判明しているかもしれませんが、古いバージョンへのフィルタリングにはしばらく時間がかかることがあります。 –

+0

コンパイラのバグのようです。 ClangはこのコードをC++ 11とC++ 14の両方として拒否します。 – StoryTeller

+0

これは最適化パスの順序に関連していますか?つまり、引数が処理される前に直接呼び出しに最適化された関数ポインタ –

答えて

8

デフォルトの引数は、関数型の一部ではないため、暗黙的に関数を関数ポインタに変換して間接的にポインタに変換すると破棄されます。

+3

次にg ++ -c -std = C++ 11はコンパイルされますか? –

+0

私は確信していませんが、私はどちらもコンパイルすべきではないと思います。 –

+1

これはうまくコンパイルされます:https://ideone.com/InD4T7 –

25

(*f)()を有効とすることは、GCCのバグです。標準の文字は、関数名を単項の*で使用すると、関数名がポインタに崩壊するはずであることを示しています。次に、ポインタを逆参照して、呼び出し式の関数アドレスを取得する必要があります。

しかし、GCCは賢明で、上記の動作は省略しています。それは(*f)を単にfと扱います。 fを呼び出すには、デフォルトの引数を使用できます。

しかし、GCCに崩壊のプリフォームを強制することができます。 Unary +を関数名に適用すると、強制的にポインタに崩壊します。だから、2次

(+f)(); 
(*+f)(); 

GCC原因GCC 7.2GCC 6.3の両方で、標準の改訂のいずれかにerror: too few arguments to functionを放出します。

+0

@StoryTellerの上にClangはOPコードをC++ 11とC++ 14で拒否したと述べています。 Clangにも同じバグがありますか? – KeithSmith

+6

@KeithSmith - **私は** StoryTellerです。そしてClangは元のコードを拒否します。ここにはバグがありません。 – StoryTeller

+0

Visual Studio 2017は元のコードをうまく使用します。 (+ f)()と(* + f)()、(+ * f)() - の両方が内部コンパイラエラーを引き起こします。 –

関連する問題