1

以下の myless のようなテンプレート化された関数ではなく、less がファンクターであるのはなぜですか? 委員会がその決定を下した理由と、さらに読むにはどこに行けばよいですか? また、C++11 標準は、委員会が特定の決定を下した理由を説明していますか?

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

#if 1

template <class T> struct stdless {
  bool operator() (const T& x, const T& y) const {return x<y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef bool result_type;
};

#else
    #define stdless std::less
#endif

//bool myless(int a, int b) { return a<b; }
template<class T>
bool myless(T a, T b) { return a<b; }

int main()
{
    vector<int> a{5, 3, 1,6};

    myless(5, 6);
    stdless<int>()(5, 6);

    auto fn1=stdless<int>();
    fn1(5,9);
    auto fn2=myless<int>;
    fn2(5,9);

    sort(a.begin(), a.end(), myless<int>);
    sort(a.begin(), a.end(), less<int>());

    for(auto b=a.begin(); b!=a.end(); ++b)
        cout << *b<<endl;
}
4

1 に答える 1

6

それにはさまざまな理由があります。operator()1つ目は、関数へのポインターを介して呼び出しをインライン化するよりも、関数への呼び出しをインライン化する方がコンパイラーにとって簡単であることです(呼び出しを行うコード自体がインライン化されていない場合)。

std::less<>そのパフォーマンス上の利点を超えて、ファンクターのさまざまな用途について、より大きな設計上の考慮事項が手元にあります。特に、 のようなソートされたコンテナーを検討してstd::set<T,Comparator>ください。myless関数へのポインターを型として直接渡すことはできないため、セットの定義を使用できるようにするには、 にする必要がstd::set<T,bool (*)(T,T)>あります。ここでの次の問題は、ポインターには、必要な機能を実行する適切なデフォルトコンストラクターがないことです。であるため、ユーザー コードはコンテナーの構築時に関数ポインターを提供する必要がありますが、これはエラーの可能性があります。

std::set<int, bool(*)(int,int)> s(&myless);

関数ポインター ( std::set<int,bool(*)(int,int)> s;) を渡すのを忘れるだけで、間違ったポインターが取得され、未定義の動作が発生します。ファンクターの場合、これは問題ではありません。コンパイラーはデフォルトでコンパレーターメンバーを構築し、それが有効なオブジェクトになります。

于 2013-09-09T14:49:01.983 に答える