[英]Passing in a functor to a functor
我正在嘗試編寫一個可以傳遞給std :: sort的函子,該函數將根據向量中對象的比較對代表另一個對象向量的索引的向量進行排序。 我不想傳入向量中的對象具有成員operator <,而是想傳遞一個謂詞,例如,如果直接對對象向量進行排序,我將傳入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個重載都不能轉換所有參數類型。
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);
嘗試這個。 現在應該可以工作了。
比較運算符需要采用const引用。 const引用不能隱式轉換為非const引用,因此編譯器表示沒有與參數類型匹配的有效重載。 只需使用此代替:
bool operator()( const ULONG & rLeft, const ULONG & rRight)
而且我建議您在另一個比較CFoo和CFoo的課程中也做同樣的事情。 當編寫一個通過引用獲取參數並且不修改這些參數值的函數時,最好始終將引用設為const,這樣將更清晰,更安全且限制更少。 當它們是非常量時,您告訴世界您希望這些參數是可修改的,而實際上它們實際上並不需要,因此您限制了該函數的可能使用,在這種情況下,這會導致問題。
正如其他人也提到的那樣,您應謹慎使用命名約定。 通常,應避免使用下划線_,因為它們在特殊的保留字或關鍵字中經常被使用(雙前划線通常用於編譯器特定指令等的保留字)。 最好避免這種情況,否則,您可能最終會發現非常奇怪的錯誤或可移植性問題。
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]);
}
};
范例 :
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或注入“可逆”比較器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.