末尾の戻り値の型、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::begin
のconst
バージョンの場合、式ints.begin()
はstd::list<int>::const_iterator
タイプの値を返します(ints
はそのようなコンテキストではconst
なので)。ただし、decltype(ints.begin())
はstd::list<int>::iterator
型を生成します。つまり、decltype
は、式の型を決定するときにbegin
メソッドのconst
修飾子を無視します。意外なことに、タイプの競合が結果です。
これは私にはGCCコンパイラのバグと思われます。 decltype
がconst
修飾子を受け入れ、const_iterator
型を生成することは意味をなさないでしょう。誰でもこれを確認したり拒否することができますか?たぶんdecltype
の仕組みで何かを見落としているかもしれませんが、これはかなり単純なシナリオのようです。
std::list<int>
だけでなく、互換性のない型を返す
const
-nessでオーバーロードされたメンバ関数を持つ型にも適用されます。
gcc 4.7.0の最近のスナップショットでエラーなしでコンパイルします。それまでは、あなたは 'ints.cbegin()'に固執していると思います。 – Cubbi
もちろん、このような単純なケースでは、これは重大な障害ではありませんでしたが、gccがすべての重要でないケース*私はそれが正しいことを確かめたい - 私は理解していない機能を使用する欲望がない)。 –