Convert a vector to initializer_list

前端 未结 6 2020
时光取名叫无心
时光取名叫无心 2021-01-31 01:26

Everyone creates std::vector from std::initializer_list, but what about the other way around?

eg. if you use a std::initializer_list

6条回答
  •  暗喜
    暗喜 (楼主)
    2021-01-31 01:52

    I posted a way that seemed to work but unfortunately caused memory access violations because of how initializer_lists are treated as references to locally-scoped copies of values.

    Here's an alternative. A separate function and a separate static initializer list is generated for each possible number of items, which are counted with a parameter pack. This is not thread safe and uses a const_cast (which is considered very bad) to write into the static initializer_list memory. However, it works cleanly in both gcc and clang.

    If for some obscure reason you need this problem solved and have no other options, you could try this hack.

    #include 
    #include 
    #include 
    #include 
    #include 
    
    namespace __range_to_initializer_list {
    
        constexpr size_t DEFAULT_MAX_LENGTH = 128;
    
        template  struct backingValue { static V value; };
        template  V backingValue::value;
    
        template  struct backingList { static std::initializer_list list; };
        template 
        std::initializer_list backingList::list = {(Vcount)backingValue::value...};
    
        template 
        static typename std::enable_if< sizeof...(Vcount) >= maxLength,
        std::initializer_list >::type generate_n(It begin, It end, It current)
        {
            throw std::length_error("More than maxLength elements in range.");
        }
    
        template 
        static typename std::enable_if< sizeof...(Vcount) < maxLength,
        std::initializer_list >::type generate_n(It begin, It end, It current)
        {
            if (current != end)
                return generate_n(begin, end, ++current);
    
            current = begin;
            for (auto it = backingList::list.begin();
                 it != backingList::list.end();
                 ++current, ++it)
                *const_cast(&*it) = *current;
    
            return backingList::list;
        }
    
    }
    
    template 
    std::initializer_list range_to_initializer_list(It begin, It end)
    {
        return __range_to_initializer_list::generate_n(begin, end, begin);
    }
    
    int main()
    {
        std::vector vec = {1,2,3,4,5,6,7,8,9,10};
        std::initializer_list list = range_to_initializer_list(vec.begin(), vec.end());
        for (int i : list)
            std::cout << i << std::endl;
        return 0;
    }
    

提交回复
热议问题