Question

I am trying to understand how to initialize private const std::map properly. I have studied this well-known topic but none of the answers was suitable for me, because I am forced to use old gcc and boost versions (gcc 4.4, boost 1.41 -> C++11 features are limited, boost::asign::map_list_of does not compile) and, moreover, I don't want to use class member function for std::map initialization due to need of doing that outside the class at the time of the object construction.

However, there is overloaded constructor for std::map that accepts two iterators (this thread inspired me too), and this is my workaround:

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)

If I uncomment the line with BOOST_ASSERT macro, this code will not be compiled, because the size of Mapping is unequal to 2 due to an error of passing the std::pair<std::string, boost::function<void(void)> > _Mapping[] into the CallbackSelector class constructor. You can verify this by looking at the output:

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

I'll be glad if someone could find this (apparently?) simple mistake. Thank you.

Était-ce utile?

La solution

There's no way to determine the size of an array given just a pointer to it. You could either pass the size as a separate argument:

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

or infer it as a template parameter:

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

or, in C++11 or later, you could take an initializer_list argument

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}
};

(Note: I took the liberty of renaming _Mapping, a reserved name that you shouldn't have been using).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top