1

C++17 は (おそらく) loop の範囲の定義を緩和しend()、異なる型 (例: センチネル) を返せるようにします:

struct MyRange {
    struct Sentinel {};
    int* begin();
    Sentinel end();
};
bool operator!=(int*, MyRange::Sentinel);

現在、これをサポートしているコンパイラは gcc 6.1 と clang 4.0+ () (エラー メッセージの例) のみです。センチネルが最後の型に対してより効率的な範囲型を作成している場合、コンパイラが緩和された範囲をサポートしているかどうかをどのように検出できますか? P0184R0 (上記のリンク) では、これに関する議論は見られません。機能テスト マクロは提供されますか?

その他の質問:

  • コンパイラのサポートを検出する方法がある場合、end()メンバー関数の戻り値の型を変更しても (ライブラリにとって) 安全ですか? たとえば、センチネルを暗黙的にイテレータ型に変換できるようにする必要がありますか?
  • 逆に、C++17 より前のコンパイラの場合、センチネルを別の名前 (例: sentinel()) で公開する価値はありますか? C++17 より前のアルゴリズムは効率的に使用できます[begin(), sentinel())か、それともコードを追加する価値はありませんか?
4

2 に答える 2

2

センチネルが効率的である理由が、センチネルの内部状態と関係があることはめったにありません。

したがって、1 つのアプローチはSentinel、それ自体の反復子バージョンを生成するのに十分な内部状態を与えることです。

均一な end-beginfor(:)ループと、同じ開始/終了反復子型を主張するアルゴリズムを使用する C++14 でも、手書きのアルゴリズムまたはループはセンチネルを使用して効率を上げることができます。

最大限のカバレッジが必要な場合は、通常、 Boost.Configのようなライブラリが最善の策ですが、C++17 機能検出セットは、この日付の時点で公開されていません (私が見つけることができます)。

私が知る限り、for(:)異なる開始/終了イテレータ タイプを受け入れるループの存在を SFINAE で検出する方法はありません。constexpr(ハッキング以外の何かを想像することはできますが、それは私のスキルを超えています。)

センチネル終了イテレータを受け入れるかどうかの検出は、<algorithms>おそらく SFINAE で行うことができます。<algorithms>しかし、C++17 がセンチネル化されたのか、あるいはそのつもりであったとしても、私には確信が持てません。range-v3 は、そのやり直しを処理することになっています。

于 2016-08-15T15:04:20.583 に答える