2012-12-30 90 views
4

有些情況下,在STL容器中有一個指針,並且不應該由指針而是由指向的對象進行小於比較。一個簡單的例子就是一個向量,它應該按照實數排序。目前,我解決這個問題有:小於函數提取指針

template<class T_PTR> struct ltDeref 
{ 
    bool operator()(T_PTR p0,T_PTR p1) const {return *p0<*p1;} 
}; 

,並用它作爲

vector<double*> vIn; 
sort(vIn.begin(),vIn.end(),ltDeref<double*>()); 

set<double*,ltDeref<double*> > someSet; 

而不是寫我自己的比較函數,有沒有在C更 「標準」 的方式++哪個不需要用戶製作模板?

+3

爲什麼設置'而不是隻設置''? – billz

+3

有些情況下,在STL容器中有指向**的指針**。在C++中不應該有一個標準的解決方案,它不需要用戶製作的模板?有些情況下,[**指針指向指針指針**](http://www.c2.com/cgi/wiki?ThreeStarProgrammer)... – Praetorian

+0

@billz這是一個簡單的例子,以減少問題最低。您可以通過指向堆上創建的某個胖對象的指針來替換double *。 – Raffi

回答

1

通常,您可以使用the functors available in functional純粹由標準構造構造一個結果分類仿函數。

但是沒有一個可以取消引用T*所以你必須使用你自己的比較器。


你可以得到的最接近的是當你的「指針」是不是原始的,但有些用戶定義型與operator*可以得到解決。

以下代碼是C++ 11(使用std::bindstd::bind1ststd::bind2nd簡單)。

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

// Fakes a "smart pointer" wrapper around data 
template <typename T> 
struct Ptr 
{ 
    Ptr(T data) : data(data) {}; 
    const T& operator*() const { return data; } 

private: 
    T data; 
}; 

int main() 
{ 
    std::vector<Ptr<double>> vIn; 
    vIn.push_back(Ptr<double>(5)); 
    vIn.push_back(Ptr<double>(2)); 
    vIn.push_back(Ptr<double>(6)); 

    using namespace std::placeholders; 
    std::sort(
     vIn.begin(), 
     vIn.end(), 
     std::bind(
      std::less<double>(), 
      std::bind(&Ptr<double>::operator*, _1), 
      std::bind(&Ptr<double>::operator*, _2) 
     ) 
    ); 

    std::vector<Ptr<double>>::const_iterator it = vIn.begin(), end = vIn.end(); 
    for (; it != end; ++it) 
     std::cout << ',' << **it; 
} 

因此,如果代替double*你有std::unique_ptr<double>std::shared_ptr<double>,那麼這可能是工作:

#include <vector> 
#include <memory> 
#include <algorithm> 
#include <functional> 
#include <iostream> 

int main() 
{ 
    typedef std::unique_ptr<double> STDUPD; 

    std::vector<STDUPD> vIn; 
    vIn.push_back(STDUPD(new double(5))); 
    vIn.push_back(STDUPD(new double(2))); 
    vIn.push_back(STDUPD(new double(6))); 

    using namespace std::placeholders; 
    std::sort(
     vIn.begin(), 
     vIn.end(), 
     std::bind(
      std::less<double>(), 
      std::bind(&STDUPD::operator*, _1), 
      std::bind(&STDUPD::operator*, _2) 
     ) 
    ); 

    std::vector<STDUPD>::const_iterator it = vIn.begin(), end = vIn.end(); 
    for (; it != end; ++it) 
     std::cout << ',' << **it; 
} 

另一個原因,以避免「原始」的指針,如果你能......

+0

謝謝你的工作。這是一個有趣的解決方案。 – Raffi

+0

它更容易使用lambda而不是綁定:'[](double * a,double * b){return * a <* b;}' – Simon

+0

@Simon:除了要使用現有的標準構造。 :)你是一個非常有效的例子,但我試圖在沒有寫出「新」類型的情況下做到這一點。 –

0

沒有現成的解決方案,其他的答案說。原始指針解引用比較器可以通過使其僅適用於具有以下顯式模板特化的原始指針類型而略微改進。我期望在使用非指針類型的情況下,這會給編譯器帶來更好的錯誤消息。

template<class T> 
struct PointeeLess; 

template<class T> 
struct PointeeLess<T const *> 
{ 
    bool operator()(T const * a , T const * b) const { return *a < *b; } 
}; 

OTOH,問題中的模板將適用於實現運算符*的非原始指針類型。