2014-03-24 94 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

我在过去使用过模板技巧来传递数组大小。像冠军一样工作。 –