号より小さいリロードで注意すべき問題-strict weak ordering 5607 ワード 機能 struct iterator express コンパイラ リプリング これは今日プログラムを書く中で出会った2つの奇妙な問題です.私のIDE はいVC++2005 ExpressiEdition . 最初の質問はmap のです.あまり話さないで、以下20 マルチラインC++ コードは私が直面した問題を再現しました.#include #include using namespace std; struct S { int x, y; S(int xx, int yy): x(xx), y(yy) {} bool operator <(const S& s) const { return x < s.x && y < s.y; } }; map ms; int main() { ms.insert(map::value_type(S(31, 41), 59)); S test(31, 59); if (ms.find(test) != ms.end()) { cout << "Find the value: "<< ms[test] << endl; } else { cout << "Find Failure/n"; } return 0; } 使用VC++6.0 , VC++2005 Express Edition, VC++2005 command line compiler( コンパイルオプションなし) , g++ テストの結果は同じで、最後に出力します.Find the value: 59 この問題は比較的隠れている.複数のコンパイラのテスト結果が同じであることは、コンパイラバージョンに関連する問題ではないことを示しています.ダイレクトデバッグアクセスfind 関数は次のことを示します. iterator find(const key_type& _Keyval) { //find an element in mutable sequence that matches _Keyval iterator _Where = lower_bound(_Keyval); return (_Where == end() || _DEBUG_LT_PRED(this ->comp, _Keyval, _Key(_Where._Mynode())) ? end() : _Where); } デバッグはいくつかありますがSTL 内部の細部は、しかし全体の実現の構想はやはり見ることができます.にあるfind 関数では、lower_bound 戻り値はノードです(31, 41) .トレースイン、呼び出しの検出_DEBUG_LT_PRED の定義は次のとおりです.#define _DEBUG_LT_PRED(pred, x, y) _Debug_lt_pred(pred, x, y, __FILEW__, __LINE__) template inline bool __CLRCALL_OR_CDECL _Debug_lt_pred(_Pr _Pred, const _Ty1& _Left, const _Ty2& _Right, const wchar_t *_Where, unsigned int _Line) { //test if _Pred(_Left, _Right) and _Pred is strict weak ordering if (!_Pred(_Left, _Right)) return (false ); else if (_Pred(_Right, _Left)) _DEBUG_ERROR2("invalid operator<", _Where, _Line); return (true ); } ( 注意:説明[ちゅうしゃく:せつめい]_Debug_lt_pred 関数には3つのリロードバージョンがあり、それぞれパラメータ_Left, _Right のconst 性質的に、これらのコードを見て多くのことを学ぶことができます.また、これらのコードを静的に見て自分のプログラムのエラーを解析すると、大量のリロード関数があるため、静的解析ではどの関数が呼び出されたのかを自分で判断することが難しく、動的デバッグでは一歩前進することができます.) この関数のコードから大体問題点がわかります.ここの_Pred パラメータは自分でstruct に定義されているoperator < を選択します._Pred のvalue はい{lessthan } , type はいstd::less しかし、ここにはもっと大きな発見があります.strict weak ordering!!! 自分自身C++ 基礎が浅いので、これは新しい発見で、すぐにgoogle ちょっと”strict weak ordering” このキーワードは、やはり大量の特集リンクを発見!ひとまずこのテーマを置いておく.問題の推測はきっとoperator < この関数は、自分のoperator < 定義:{31, 41} < {31, 59} 戻り値Yesfalse , {31, 59} < {31, 41} の戻り値もfalse では、この2つの比較から結論を出すことができます.{31, 41} == {31, 59} !!! これもプログラムの実行が望ましくない結果を返すのも無理はない.しかし、これは推測にすぎません.デバッグを続けて、見つけられるかどうか見てみましょう._Pred 関数の真の姿.コンパイラから見ると_Pred のtype はいstd::less で、MSDN で行ないます.less はいSTL のテンプレートクラスです.MSDN で参照できます..less less template<class T> struct less : public binary_function <T, T, bool> { bool operator() (const T& x, const T& y) const; };The template class defines its member function as returning x < y . The member function defines a total ordering , even if T is an object pointer type. デバッグしてアクセスを追跡します_Pred 関数では、次のように定義されています.template struct less : public binary_function<_Ty, _Ty, bool > { //functor for operator< bool operator ()(const _Ty& _Left, const _Ty& _Right) const { //apply operator< to operands return (_Left < _Right); } }; 最終的に比較します_Left および_Right に呼び出されたのはstruct S で定義したoperator < . これで問題の真相が明らかになった.2つのトピックが残っています.1つはstrict weak ordering あ、もう一つはSTL のいくつかの実現方法は、以上がデバッグ過程を追跡して沿道で見たものを機械的に記録しただけなので、本当の理解ではありません. 今日はもう一つの問題に直面しましたSTL タブで行います.sort 関数の問題、この問題はただVC++ 2005 Express Edition に表示され、コマンドラインで使用されます.cl.exe オプションなしで接続をコンパイルする場合は通常、g++ 正常です.問題の表現は、プログラムが実行中に異常が発生したことです.情報は次のとおりです.”invalid operator <” .この問題はデバッグを再現しません.その解決方法は次のアドレスを参照してください.http://support.microsoft.com/kb/949171 strict weak ordering 数学の用語で、さっき与えられたこのアドレスにはstrict weak ordering の簡明な解釈を貼ってください.The STL algorithms for stable_sort ( ) and sort() require the binary predicate to be strict weak ordering. For example: · Strict: pred (X, X) is always false. · Weak: If ! pred (X, Y) && !pred (Y, X), X==Y. · Ordering: If pred (X, Y) && pred (Y, Z), then pred (X, Z). [Rails]simple_calendarの導入方法 Rails APIサーバー開発時に入れたGemの使い方 (rack-cors, rspec-rails, factory_bot_rails, rubocop)