2014-03-24 111 views
1

我想了解如何初始化私有const std::map正確。我研究了this着名的話題,但沒有一個答案適合我,因爲我不得不使用舊的gcc和boost版本(gcc 4.4,boost 1.41 - > C++ 11功能有限,boost::asign::map_list_of does not compile),而且,因爲在構造對象時需要在類之外進行,所以我不想使用類成員函數進行std :: map初始化。用std :: pairs數組初始化std :: map問題(指針錯誤?)

然而,過載構造函數std::map接受兩個迭代器(this線程啓發了我太多),這是我的解決辦法:

template <typename Arg, typename Callback> 
class CallbackSelector 
{ 
    private: 
     const std::map<Arg, Callback> Mapping; 

    public: 
     CallbackSelector(std::pair<Arg, Callback> _Mapping[]): 
      Mapping(_Mapping, _Mapping + sizeof(_Mapping)/sizeof(std::pair<Arg, Callback>)) 
      { 
       //BOOST_ASSERT(sizeof _Mapping)/(sizeof (std::pair<Arg, Callback>)) == 2); 
       std::cout << "sizeof _Mapping " << sizeof _Mapping << std::endl; 
       std::cout << "sizeof (std::pair<Arg, Callback>) " << sizeof (std::pair<std::string, boost::function<void(void)> >) << std::endl; 
      }; 
}; 

void PamEvent() {} 

void DefaultEvent() {} 

int main(int argc, char** argv) 
{ 
    std::pair<std::string, boost::function<void(void)> > _Mapping[] = 
    { 
     std::make_pair("pam:", boost::bind(&PamEvent)), 
     std::make_pair("none", boost::bind(&DefaultEvent)) 
    }; 
    std::cout << "sizeof _Mapping " << sizeof _Mapping << std::endl; 
    std::cout << "sizeof (std::pair<Arg, Callback>) " << sizeof (std::pair<std::string, boost::function<void(void)> >) << std::endl; 

    CallbackSelector<std::string, boost::function<void(void)> > Selector(_Mapping); 
} 

(The full executable version of this example)

如果我取消了符合BOOST_ASSERT宏,因爲將std::pair<std::string, boost::function<void(void)> > _Mapping[]傳入CallbackSelector類構造函數的錯誤導致Mapping的大小不等於2,所以不會編譯此代碼。您可以通過查看輸出來驗證:

sizeof _Mapping 80         //in the int main() 
sizeof (std::pair<Arg, Callback>) 40 

sizeof _Mapping 8         //in the CallbackSelector constructor 
sizeof (std::pair<Arg, Callback>) 40    //the array size has decreased tenfold 

我會很高興,如果有人能找到這個簡單的錯誤(顯然?)。謝謝。

+1

關於大小,'_Mapping []'作爲函數參數只是一個指針。 – juanchopanza

回答

2

沒有辦法確定只給它一個指針的數組的大小。您既可以通過大小作爲單獨的參數:

CallbackSelector(std::pair<Arg, Callback> mapping[], size_t size) : 
    Mapping(mapping, mapping + size) 

或推斷它作爲一個模板參數:

template <size_t size> 
CallbackSelector(std::pair<Arg, Callback> (&mapping)[size]) : 
    Mapping(mapping, mapping + size) 

,或者在C++ 11或更高版本,你可以採取initializer_list參數

CallbackSelector(std::initializer_list<std::pair<Arg, Callback>> mapping) : 
    Mapping(mapping.begin(), mapping.end()) 

// Usage example 
CallbackSelector<std::string, boost::function<void(void)> > selector { 
    {arg1, callback1}, 
    {arg2, callback2} 
}; 

(注:我把重命名_Mapping的自由,一個reserved name,你不應該一直在使用)。

+0

謝謝你的一個驚人的答案。即使使用我的舊版gcc 4.4.7,最後一個選項仍然有效。如果您不介意我將模板定義添加到代碼示例中。 –

+0

我在過去使用過模板技巧來傳遞數組大小。像冠軍一樣工作。 –