2

社内のあるプロジェクトから別のプロジェクトにコードを移植しているときに、コンパイルされない一般的な「sets_intersect」関数に遭遇しました。

template<typename _InputIter1, typename _InputIter2, typename _Compare>
bool sets_intersect(_InputIter1 __first1, _InputIter1 __last1,
                    _InputIter2 __first2, _InputIter2 __last2,
                    _Compare __comp)
{
    // Standard library concept requirements
    // These statements confuse automatic indentation tools.
    // concept requirements
    __glibcpp_function_requires(_InputIteratorConcept<_InputIter1>)
    __glibcpp_function_requires(_InputIteratorConcept<_InputIter2>)
    __glibcpp_function_requires(_SameTypeConcept<
          typename iterator_traits<_InputIter1>::value_type,
          typename iterator_traits<_InputIter2>::value_type>)
    __glibcpp_function_requires(_OutputIteratorConcept<_OutputIter,
          typename iterator_traits<_InputIter1>::value_type>)
    __glibcpp_function_requires(_BinaryPredicateConcept<_Compare,
          typename iterator_traits<_InputIter1>::value_type,
          typename iterator_traits<_InputIter2>::value_type>)

    while (__first1 != __last1 && __first2 != __last2)
    if (__comp(*__first1, *__first2))
            ++__first1;
    else if (__comp(*__first2, *__first1))
            ++__first2;
    else {
            return true;
    }
    return false;
}

私はこの「概念」の概念に慣れていないので(駄洒落で申し訳ありません)、c ++標準ライブラリを少し調べてグーグルで調べたところ、これらの__glibcpp_function_requiresマクロがに変更されたことがわかります__glibcxx_function_requires。これでコンパイラエラーが修正されました。ただし、これは私にとって初めてのことなので、このコードが私のために何をしているかに興味があり、ライブラリ内のドキュメントを見つけたり、コードを解読したりするのに問題があります。

これらのマクロのポイントは、コンパイラがテンプレート化された関数を展開すると、コンパイル時に型チェックを実行して、使用されているコンテナがこのアルゴリズムと互換性があるかどうかを確認することだと思います。つまり、最初の呼び出しは、に_InputIter1準拠するチェックであると想定してい_InputIteratorConceptます。私は混乱しているだけですか、それとも正しい方向に進んでいますか?また、これらのマクロの名前がc ++標準ライブラリで変更されたのはなぜですか?

4

4 に答える 4

3

「コンセプト」は の次のバージョンで提案された機能でしたが、C++(比較的) 最近投票で標準から除外されたため、しばらく引用する予定はありません。

これらは、テンプレート パラメーターの要件を早期にチェックできるように設計されており、特に、必要な制約を満たさない型がテンプレートのインスタンス化に使用された場合に、はるかに簡潔なエラー メッセージを有効にすることができます。

2 番目の編集: (dribeas と Jerry Coffin のコメントを参照) これらの g++ マクロは、内部概念チェック メカニズムであり、提案されている同名の新しい言語機能とは直接関係ありません。これらは g++ の内部にあるため、関数テンプレートの機能を失うことなく、安全に削除できます (おそらく削除する必要があります)。

于 2009-10-27T22:17:34.590 に答える
1

2 つの概念概念 (しゃれた意図) があります。定義されている標準には、コンパイルに役立つ標準言語機能としての概念の提案がありました... C ++ 0xの概念、議論についてはかなりの文献があります...

もう1 つの概念概念は、今ヒットした概念です。g++ 実装で展開される STL には、エラー検出を支援するための特定の実装者チェックがあります。これらは、言語機能ではなく、プログラマーが使用するためのものではなく、ライブラリ内で内部的に使用されるという点で、以前の概念とは異なります。名前は予約されている (2 つのアンダースコアで始まる) ため、コンパイラ/ライブラリの実装者は、ライブラリの動作が標準で定義されているものと異ならない限り、そこに自由に追加できます。

あなたがしていることに戻る: 新しいコンパイラに移植しようとしているコードはstd::set_intersect、標準 [lib.set.intersection] で定義されているように、全体を解析することなく交差するかどうかのみを返すように修正されたバージョンです。 2 つの範囲。標準バージョンを使用して、出力反復子が変更されていないことを確認するか、パフォーマンスの問題である場合は、非標準の隠しコンパイラ定義シンボルに応じて、概念チェックなしで実装し、コンパイラのアップグレード時にメンテナンスの問題を求めています。 . しかし、あなたがすでに知っていること。

于 2009-10-27T22:47:52.110 に答える
1

あなたは正しいです。最初の呼び出しは、_InputIter1「入力イテレータ」の概念を実装することを確認しています。

これらのマクロは GLIBC 実装の内部詳細 (アンダースコアまたは 2 つのアンダースコアで始まる) であるため、GLIBC 実装者は自由に変更することができます。ユーザーのコードで使用することは想定されていません。

「概念」は C++0x ドラフトの一部ではなくなったため、ポータブルな概念チェックを行うには、Boost Concept Check Libraryなどのサードパーティ ライブラリを使用する必要があります。

于 2009-10-27T22:29:08.530 に答える