2011-02-03 7 views
2

私は、std :: sortに渡すことができるファンクタを記述しようとしています。これは、ベクトルのオブジェクトの比較に基づいて、オブジェクトの別のベクトルのインデックスを表すベクトルをソートします。ベクトルのオブジェクトにはメンバー演算子<があると仮定するのではなく、オブジェクトのベクトルを直接ソートする場合はstd :: sortに渡すなどの述語を渡したいと思います。ファンクタにファンクタを渡す

template <class T, class _Pr> 
class SortIndexVectorObjectsHelper : public std::binary_function<ULONG, ULONG, bool> 
{ 
    ULONG m_ulSize; 
    std::vector<T> & m_aItems; 
    BOOL m_bSortAscending; 
    _Pr m_Comp; 

public: 

    SortIndexVectorObjectsHelper(std::vector<T> & aItems, _Pr Comp) : m_aItems(aItems), m_Comp(Comp), m_ulSize(0) 
    { 
     m_ulSize = m_aItems.size(); 
    } 

    bool operator()(ULONG & rLeft, ULONG & rRight) 
    { 
     if (rLeft < m_ulSize && rRight < m_ulSize) 
     { 
      T & pLeft = m_aItems[rLeft]; 
      T & pRight = m_aItems[rRight]; 

      if (pLeft && pRight) 
      { 
       return m_Comp(pLeft, pRight); 
      } 
     } 
     return false; 
    } 


}; 

struct SortFooByX: public std::binary_function<CFoo,CFoo, bool> 
{ 
    BOOL m_bSortAscending; 

    SortFooByX(BOOL bSortAscending) 
    { 
     m_bSortAscending = bSortAscending; 
    } 

    bool operator()(CFoo & _Left, CFoo & _Right) 
    { 

     if (m_bSortAscending) 
     { 
     if (_Left.X() < _Right.X()) 
      return true; 
     } 
     else 
     { 
     if (_Left.X() > _Right.X()) 
        return true; 

      } 

      return false; 
    } 


}; 

std::sort(aFooIndicies.begin(), aFooIndicies.end(), SortIndexVectorObjectsHelper<CFoo, std::binary_function<CFoo, CFoo, bool> >(aFoo, SortFooByX(FALSE))); 

これをコンパイルすると、2つのオーバーロードのいずれも、すべての引数タイプを変換できないというエラーが表示されます。

+0

あなたの 'operator()'は 'const T&'型の2つの引数を受け取り、 'ULONG'を受け取るように設計されていると思います。 –

+1

_Prは予約済みの識別子です。それを使用しないでください。 –

答えて

0
std::sort(aFooIndicies.begin(), aFooIndicies.end(), SortIndexVectorObjectsHelper<CFoo, std::binary_function<CFoo, CFoo, bool> >(aFoo, SortFooByX(FALSE))); 

SortIndexVectorObjectsHelperの第2引数は間違っています。次のようにタイプはSortFooByXである必要があります。

SortIndexVectorObjectsHelper<CFoo, SortFooByX> comparer(aFoo, SortFooByX(FALSE)); 
std::sort(aFooIndicies.begin(), aFooIndicies.end(), comparer); 

これを試してください。今はうまくいくはずです。

+0

私はそうは思わない、一時的なオブジェクトはちょうど(OPのコードのように)うまくいくはずです。問題は不安です。比較関数に必要なプロトタイプは、const参照(または値)を取る必要があります。 –

+0

@Mikael:修正は一時的なものではありません。クラステンプレートの正しい*タイプ*についてです。私は 'comparer'変数を読みやすいように宣言しました。 OPのコードの 'SortIndexVectorObjectsHelper'の2番目の' type'を見てください。 – Nawaz

0

比較演算子はconst参照を取る必要があります。 const参照を暗黙的に非const参照に変換することはできないため、コンパイラはパラメータ型と一致する有効なオーバーロードがないと示します。

bool operator()(const ULONG & rLeft, const ULONG & rRight) 

また、CFooとCFooを比較する他のクラスでも同じことをお勧めします。参照によってパラメータを取得し、それらのパラメータの値を変更しない関数を書くときは、参照をconstにするほうが、より明確で、安全で、制限が少なくなります。それらが非constのときは、それらのパラメータを変更可能にする必要があることを世界に伝える必要があります。そのため、関数の可能な使用を制限します。この場合、これは問題を引き起こしています。

他にも言及したように、命名規則には注意が必要です。一般に、特別な予約語やキーワードでは一見よく使われているため、アンダースコアは避けてください(二重のアンダースコアはコンパイラ固有の命令などの予約語によく使われます)。ちょうどそれを避けるほうがいいです。さもなければ、非常に奇妙なバグや移植性の問題に直面するかもしれません。

0
template<class Lookup, class Compare> 
struct LookupCompare { 
    Lookup &lookup; 
    Compare cmp; 

    LookupCompare(Lookup &lookup, Compare cmp=Compare()) : lookup (lookup), cmp (cmp) {} 

    template<class T> 
    bool operator()(T const &a, T const &b) { 
    return cmp(lookup[a], lookup[b]); 
    } 
}; 

Example

struct Less { 
    template<class T> 
    bool operator()(T const &a, T const &b) { 
    return std::less<T>()(a, b); 
    } 
}; 

template<class Lookup> 
LookupCompare<Lookup, Less> lookup_compare(Lookup &lookup) { 
    return lookup; 
} 
template<class Lookup, class Compare> 
LookupCompare<Lookup, Compare> lookup_compare(Lookup &lookup, Compare cmp) { 
    return LookupCompare<Lookup, Compare>(lookup, compare); 
} 

int main() { 
    vector<int> lookup; 
    lookup.push_back(42); 
    lookup.push_back(3); 
    lookup.push_back(5); 

    vector<int> data; 
    data.push_back(0); 
    data.push_back(1); 
    data.push_back(2); 

    cout << data << '\n'; 
    sort(data.begin(), data.end(), lookup_compare(lookup)); 
    cout << data << '\n'; 

    return 0; 
} 

私はなぜあなたはm_ulSizeを使用しているか分からないので、私はそれを残してきました。私もかなり簡素化しており、LookupCompareは現在10 SLOCに適合しています。特に、昇順のフラグは必要ありません。std :: lessをstd :: lessにスワップするか、または「反転」コンパレータを挿入することができます。

関連する問題