2011-02-03 55 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&`的参数,并且你将它设计为接收`ULONG`。 – 2011-02-03 18:41:26

+1

_Pr是保留的标识符;不要使用它。 – 2011-02-03 18:45:31

回答

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

SortIndexVectorObjectsHelper中的第二个参数类型错误。该类型应该是SortFooByX,如下图所示:

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

尝试此。它现在应该工作。

0

比较运算符需要采用const引用。 const引用不能隐式转换为非const引用,所以编译器说没有与参数类型相匹配的有效重载。只需使用此代替:

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

而且我建议你在其他类比较CFoo和CFoo相同。当你编写一个通过引用接受参数的函数并且不修改这些参数的值时,最好总是使参考为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 :: greater或注入一个“反转”比较器。

相关问题