2009-07-15 39 views
56

GCC 4.3で初めてCCCコードをコンパイルしたとき(私は、4.1、4.0、3.4の警告なしで、-Wall -Wextraオプションで正常にコンパイルした後)、突然フォームwarning: type qualifiers ignored on function return typeのエラーの束。Pedantic gcc警告:関数の戻り値のタイプ修飾子

temp.cpp考えてみましょう:

class Something 
{ 
public: 
    const int getConstThing() const { 
     return _cMyInt; 
    } 
    const int getNonconstThing() const { 
     return _myInt; 
    } 

    const int& getConstReference() const { 
     return _myInt; 
    } 
    int& getNonconstReference() { 
     return _myInt; 
    } 

    void setInt(const int newValue) { 
     _myInt = newValue; 
    } 

    Something() : _cMyInt(3) { 
     _myInt = 2; 
    } 
private: 
    const int _cMyInt; 
    int _myInt; 
}; 

g++ temp.cpp -Wextra -c -o blah.oの実行:

temp.cpp:4: warning: type qualifiers ignored on function return type 
temp.cpp:7: warning: type qualifiers ignored on function return type 

誰かがC++標準に違反している私が間違っているのを教えすることはできますか?私は値で返ってくると、先導constは余分ですが、私はなぜそれを使って警告を生成する必要があるのか​​理解できないと思います。私がconstを離れなければならない他の場所はありますか?

+0

このような質問と回答を参照してください:http://stackoverflow.com/questions/1607188/why-is-type-qualifier-on-return-type-is-meaningless –

+7

これまでのような警告が表示されています私はコード内で何が起こっていたのか理解しようと数分を費やしました。おそらく、より良いエラー報告は物事をスピードアップするでしょう。 'warning:type修飾子は関数の型を無視して型を返す'の代わりに、 'warning:' valueで返すときにconst修飾子を付けないでください 'のようになります。 – Avio

答えて

77

これは規格に違反していません。だから彼らはの警告で、のエラーはではありません。

本当にあなたが正しいです - 先導constは余分です。コンパイラは、他の環境で何かを意味するコードを追加したため警告しますが、この状況では何も意味しません。後で戻り値が変更可能になったときに後で失望しないようにしたいと考えています。

+13

それは警告であり、エラーではないことは何も意味しません。'sizeof(void) 'のような他の無効なコードも単に警告するだけですが、明らかに禁止されています。スタンダードは、警告とエラーの違いを認識していません。どちらも診断です。 –

+1

@litb:彼が言ったことはまだ正しいです。もちろん、警告であるということは、あなたが言うように標準に違反しないことを保証するものではありませんが、エラーの代わりに警告を出される理由は、コンパイラの実装者が禁止したくないということですそれ。それを禁止したくない理由は、それが基準に違反していないからです。 – jalf

+1

標準に全く違反していますか? – Philipp

17

Boost.ProgramOptionsを使用するコードをコンパイルするときにこの警告が発生しました。私は-Werrorを使用して警告がビルドを殺していたが、警告のソースがBoostの深さにあったので、私のコードを修正することでそれを取り除くことができなかった。このことができます

-Wno-ignored-qualifiers 

希望:

はずっと掘削後、私は警告を無効にするコンパイラオプションを発見しました。

+4

私は同じ問題を抱え、 '-I'の代わりに' -isystem'でBoostのインクルードパスを設定しました。これはBoostヘッダによって引き起こされるすべての警告を抑制します。 – Philipp

+0

@ Philippの解決策は正しいです。 -Wno-ignored-qualifierを使用すると、コードに影響を及ぼし、作成した警告をコンパイラーが発行しないようにしますが、Philippのソリューションは独自のコードによって生成される警告に影響しません。 – Wond3rBoi

-5

Scott Meyersには、誰かがconstの値を返すことになる理由があることが指摘されています。ここに例があります:

int some_calculation(int a, int b) { int res = 0; /* ... */ return res; } 

/* Test if the result of the calculation equals 40.*/ 
if (some_calculation(3,20) = 40) 
{ 

} 

あなたは私が間違っていたものを見ていますか?このコードは絶対に正しいので、コンパイルする必要があります。問題は、に40を代入するのではなく、を比較しようとしていることをコンパイラが理解していないことです。

戻り値がconstの場合、上記の例はコンパイルされません。コンパイラがキーワードconstを破棄しない場合は、少なくとも。

+14

いいえ、コンパイルしないでください。 'some_calculation'の結果はint型のrvalueです。非クラス型の右辺値には割り当てることはできません。 –

+1

戻り値がクラス型の場合、 'const'は正しいので警告を生成しません。 – Philipp

+0

実際にこの例をコンパイルしようとしましたか? GCCは "error:左辺オペランドとして必要な左辺値"を与えます。clang ++は "error:expression is assignable"を返します。 – Bulletmagnet

2

この

struct Foo { Foo(int) {} operator bool() { return true; } };

その

Foo some_calculation(int a, int b) { Foo result(a + b); /*...*/ return result; }

if (some_calculation(3, 20) = 40) { /*...*/ }

が警告なしでコンパイル例を有します。もちろん、これはまれです。しかし、人々が間違ってやることを困難にすることについてのconstの正しさはありませんか?そして人々が物事を試すことを期待して、それは間違っています。戻り値の型はconst宣言されるべきです。 そして、g ++はクラシファイアを無視することについて警告しますが、無視しません。私は、警告は、コピーを取ってそのコピーのconstクラシファイアを無視するユーザに関する警告だと思います。しかし、これは絶対に正しい行動であるため、警告であってはなりません。そして、これを行うことが理にかなっています。

+3

'const'を追加した場合、G ++はここで警告しません。 'const'修飾子は、非クラス型の戻り値に対してのみ無視されます。 – Philipp

1

-pedanticでは、ISO標準を厳密に守らないといけませんか?当然の-std =に応じて...

1

この警告も変更すべきではないオブジェクトへのポインタを返す関数を宣言する際の混乱を避けるために役立ちます。

とき一定の値だけ理にかなって返す
// "warning: type qualifiers ignored on function return type" 
// as the pointer is copied. 
Foo* const bar(); 

// correct: 
const Foo* bar(); 
4

呼び出し元が参照先(指し示す)値を変更できるため、参照またはポインタ(この場合は定数へのポインタで、定数ポインタではない)を返します。

コードではありませんあなたの質問に関連した上で別のコメント

: は、私はそれがあるべきでしょう代わりに

int& getNonconstReference() { 
    return _myInt; 
} 

のセッターを使用する方が良いと思う。また

void setMyInt(int n) { 
    _myInt = n; 
} 

は、それが無用ですconst参照をintに返します。コピーや移動がより高価な、より大きなオブジェクトには意味があります。

0

constは基本タイプの結果(無視されます)とconst(一般的には大混乱を招くクラスタイプの結果)の違いがあります。

namespace i { 
    auto f() -> int const { return 42; } 
    void g(int&&) {} 
} 

namespace s { 
    struct S {}; 
    auto f() -> S const { return {}; } 
    auto g(S&& ) {} 
} 

auto main() -> int 
{ 
    { using namespace i; g(f()); } // OK 
    { using namespace s; g(f()); } // !The `const` prevents this. 
} 

コンパイラは最初の場合に警告する理由はここにある:それは1つが単純に期待できる何をしないことがあり、特殊な場合、です。

最近のプログラミングでは、移動のセマンティクスが禁止されているので、クラスタイプの結果についてはconstに関する警告が表示されます。 1つの想像されたどんな小さな利点でもかなりのコストです。