我正在尝试编写一个可以传递给std::sort的函数器,它将根据向量中对象的比较对表示另一个对象向量的索引的向量进行排序。我不想假设向量中的对象有一个成员排序,而是希望传入一个谓词,比如如果我直接对对象的向量进行排序,我会传递给std::operator<。
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)));编译这个代码会给我一个错误,两个重载都不能转换所有的参数类型。
发布于 2011-02-04 03:01:27
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);尝尝这个。它现在应该可以工作了。
发布于 2011-02-04 03:03:18
比较运算符需要接受常量引用。常量引用不能隐式转换为非常数引用,因此编译器表示没有与参数类型匹配的有效重载。只需使用下面的代码:
bool operator()( const ULONG & rLeft, const ULONG & rRight)我建议您在比较CFoo和CFoo的另一个类中执行相同的操作。当您编写一个通过引用获取参数并且不修改这些参数的值的函数时,最好始终将引用常量设置为常量,这样会更清晰、更安全、限制更少。当它们是非常数时,你告诉世界你希望这些参数是可修改的,而实际上它们不需要修改,所以你限制了函数的可能使用,在这种情况下,这导致了问题。
正如其他人也提到的,您应该小心您的命名约定。通常,您应该避免使用前导下划线_,因为它们经常用于特殊的保留字或关键字(双前导下划线通常用于编译器特定指令等的保留字)。最好避免它,否则,您最终可能会遇到非常奇怪的bug或可移植性问题。
发布于 2011-02-04 03:04:34
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可以运行在10SLOC上。特别是,它不需要升序标志,因为您可以将std::less替换为std::need或注入一个“反转”比较器。
https://stackoverflow.com/questions/4890167
复制相似问题