5

アルゴリズム内で、const への参照によって要素を受け入れるラムダを作成したいと考えています。

template<typename Iterator>
void solve_world_hunger(Iterator it)
{
    auto lambda = [](const decltype(*it)& x){
        auto y = x;   // this should work
        x = x;        // this should fail
    };
}

コンパイラは次のコードを好みません。

エラー: »const«-qualifier は »int&« に適用できません (ドイツ語から手動で翻訳)

それから私はそれがすでに参照されていることに気づきました、そしてdecltype(*it)もちろんそれらは作ることができませんconst. を削除すると、コードはコンパイルされますが、失敗しconstたいと思います。x = x

プログラマー (私です) をしばらく信頼して、とにかく、参照の崩壊規則のために削除されるconst明示的な とを取り除きましょう。&しかし、待ってください、decltype(*it)実際には参照であることが保証さ&れていますか、それとも安全のために明示的に追加する必要がありますか?

プログラマーを信用できない場合、問題を解決するための 2 つの解決策を考えることができます。

(const typename std::remove_reference<decltype(*it)>::type& x)

(const typename std::iterator_traits<Iterator>::value_type& x)

どちらが醜いかは自分で決めることができます。理想的には、テンプレートのメタプログラミングを一切含まないソリューションが必要です。なぜなら、私の対象読者はそれを聞いたことがないからです。そう:

質問 1: はdecltype(*it)&常に と同じdecltype(*it)ですか?

質問 2: テンプレートのメタプログラミングなしで const への参照によって要素を渡すにはどうすればよいですか?

4

1 に答える 1

4

質問1:いいえ、InputIteratorの要件は、単に*itTに変換できるものです(「Iterator要件」の表72)。

たとえばdecltype(*it)、がconst char&であるイテレータの場合がvalue_typeありますint。またはそれは可能性がありますint。またはdouble

を使用することは、を使用することiterator_traitsと同じではありません。どちらを使用decltypeするかを決定します。

同じ理由で、auto value = *it;は必ずしもイテレータの値型を持つ変数を提供するわけではありません。

質問2:テンプレートメタプログラミングの意味によって異なる場合があります。

iterator_traitsトレイトタイプの使用がTMPの場合、任意のイテレータの値タイプにアクセスする唯一の手段であるため、TMPなしで「イテレータの値タイプへの定数参照」を指定する方法はありません。

構成したい場合は、decltypeこれはどうですか?

template<typename Iterator>
void solve_world_hunger(Iterator it)
{
    const auto ret_type = *it;
    auto lambda = [](decltype(ret_type)& x){
        auto y = x;   // this should work
        x = x;        // this should fail
    };
}

そのタイプを使用するにはキャプチャする必要があるかもしれませんがret_type、現時点では簡単に確認できません。

残念ながら、イテレータを余分に逆参照します。それを回避するために賢いコードを書くこともできますが、賢いコードは最終的にはremove_referenceTMPの代替バージョンになります。

于 2013-01-18T12:20:50.337 に答える