2014-02-09 45 views
3

我知道,一旦聲明,就無法更改地圖的順序。相反,我在一個結構試圖這樣:取決於輸入值對std :: map的排序順序

struct MyStruct 
{ 
    std::map<int, double>* my_map; 

    MyStruct(bool dir) 
    { 
     if(dir) 
     { 
      my_map = new std::map<int, double, std::less<int> >; 
     } 
     else 
     { 
      my_map = new std::map<int, double, std::greater<int> >; 
     } 
    } 
} 

這不是工作,並抱怨說,我改變了else條件下的類型。有沒有解決的辦法?我能想到的唯一方法是編寫我自己的比較器並創建一個封裝bool dir的對象,這似乎是多餘的。

+2

是在編譯時知道你是否希望'less'或'greater'?或僅在運行時? –

+0

@JosephMansfield只在運行時不幸。 – Joshua

+0

我想你將不得不編寫自己的比較器。但是,別人可能有更好的主意。但是在旁註中:如果你想編寫適當的C++,將映射封裝在'std :: unique_ptr'中,並使用(如果在編譯器中可用)'std :: make_unique'來創建映射。這樣你就不必在意在析構函數中釋放映射。 – Excelcius

回答

5

std::map將比較對象作爲模板參數,所以要做你想做的事,你需要一個可以在運行時改變行爲的類型。

struct MoreOrLess 
    { 
     bool useLess; 
     template <class T, class U> 
     bool operator()(const T &t, const U &u) const 
     { 
     if(useLess) return t < u; 
     else return t > u; 
     } 
    }; 

    struct MyStruct 
    { 
     std::map<int, double, MoreOrLess> my_map; 

     MyStruct(bool dir) :my_map(MoreOrLess{dir}) {} 
    }; 

這種方式,比較算符具有(在std::map使用)相同的類型,無論使用std::lessstd::greater的。

+0

不妨試試指針,並在初始化程序列表中初始化映射。 –

+0

@BenjaminLindley我同意,我只是不想更改OP的示例。 – SirGuy

+0

@GuyGreer我喜歡這個解決方案以及jrok的。我會試着看看哪一個更適合我的目的。謝謝。 – Joshua

0

這裏有一個簡單的辦法,雖然可能不是最有效的:

struct MyStruct 
{ 
    typedef std::function<bool(int,int)> Predicate; 
    std::map<int,double,Predicate> my_map; 

    static Predicate predicateFor(bool dir) 
    { 
     if (dir) return std::less<int>(); 
     return std::greater<int>(); 
    } 

    MyStruct(bool dir) : my_map(predicateFor(dir)) { } 
};