2011-08-31 13 views
16

末尾の戻り値の型、decltypeとconst - ness

#include <list> 

class MyContainer{ 
    std::list<int> ints; 

    auto begin() -> decltype(ints.begin()) 
    { 
    return ints.begin(); 
    } 

    auto begin() const -> decltype(ints.begin()) 
    { 
    return ints.begin(); 
    } 
}; 

このコードが無意味であるという事実を無視してください。重要な部分は、GCC 4.6.1(-std=c++0xフラグ付き)を使用するときに生成されるコンパイラエラーです。

In member function 'std::list<int>::iterator MyContainer::begin() const': 
error: could not convert '((const MyContainer*)this)->MyContainer::ints.std::list<_Tp, _Alloc>::begin [with _Tp = int, _Alloc = std::allocator<int>, std::list<_Tp, _Alloc>::const_iterator = std::_List_const_iterator<int>]()' from 'std::list<int>::const_iterator {aka std::_List_const_iterator<int>}' to 'std::list<int>::iterator {aka std::_List_iterator<int>}' 

テンプレートを使用したときのエラーのファンではない場合、短編小説はMyContainer::beginconstバージョンの場合、式ints.begin()std::list<int>::const_iteratorタイプの値を返します(intsはそのようなコンテキストではconstなので)。ただし、decltype(ints.begin())std::list<int>::iterator型を生成します。つまり、decltypeは、式の型を決定するときにbeginメソッドのconst修飾子を無視します。意外なことに、タイプの競合が結果です。

これは私にはGCCコンパイラのバグと思われます。 decltypeconst修飾子を受け入れ、const_iterator型を生成することは意味をなさないでしょう。誰でもこれを確認したり拒否することができますか?たぶんdecltypeの仕組みで何かを見落としているかもしれませんが、これはかなり単純なシナリオのようです。

注:私が知る限り、同じ動作は std::list<int>だけでなく、互換性のない型を返す const -nessでオーバーロードされたメンバ関数を持つ型にも適用されます。

+2

gcc 4.7.0の最近のスナップショットでエラーなしでコンパイルします。それまでは、あなたは 'ints.cbegin()'に固執していると思います。 – Cubbi

+0

もちろん、このような単純なケースでは、これは重大な障害ではありませんでしたが、gccがすべての重要でないケース*私はそれが正しいことを確かめたい - 私は理解していない機能を使用する欲望がない)。 –

答えて

10

あなたは正しいです、これはバグです。 N3291、セクション5.1.1によれば、第3項:

宣言は、クラスXのメンバ関数またはメンバ関数テンプレートを宣言した場合、式は、このタイプのprvalueある「ポインタCV-クアリのfi ER-配列にオプションのcv-qualifer-seqと関数定義の終わり、メンバー宣言子、宣言子の間に "X"を付けます。オプションのcv-qualifier-seqの前に現れてはならず、静的メンバ関数の宣言内に現れてはならない(ただし、その型と値のカテゴリは非静的メンバ関数内にあるので静的メンバ関数内で定義される) 。 [注意:これは、宣言が完全になるまで宣言の一致が起こらないためです。 -end note]他のコンテキストのオブジェクト式とは異なり、*これは、メンバ関数本体の外部でクラスメンバアクセス(5.2.5)のために完全な型である必要はありません。 [注:宣言の前に宣言されているクラスメンバーだけが表示されます。 -end note]

しかしこれは、最後の作業草案とN3291の間の最近の変更です。だからGCCは6ヶ月前よりもずっと短かった。これは、動く仕様にコードを書く危険です。

+0

それは最後のドラフトについていくつかの議論を思い出して、後のリターンタイプで 'this'を使用していたので、私の考えの一部でしたが、実際に受け入れられた提案があるかどうかはわかりませんでした。十分に言及された答えをありがとう。ありがたいことに(Cubbyのコメントによると)、バージョン4.7はすでにこの変更に対処しているので、GCCはこの上にうまくいくように見えます。 –

関連する問題