Convert a vector to initializer_list

前端 未结 6 1911
时光取名叫无心
时光取名叫无心 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 02:15

    The answer is NO, you cannot do that.

    An object of type std::initializer_list is a lightweight proxy object that provides access to an array of objects of type T. A std::initializer_list object is automatically constructed when:

    • a braced-init-list is used in list-initialization, including function-call list initialization and assignment expressions (not to be confused with constructor initializer lists)
    • a braced-init-list is bound to auto, including in a ranged for loop

    As far as library support goes, std::initializer_list only has a default constructor that constructs an empty list, and its iterators are constant. The lack of a push_back() member means you cannot apply e.g. a std::copy with a std::back_inserter iterator adaptor to fill it, and neither can you assign through such iterators directly:

    #include 
    #include 
    #include 
    #include 
    
    int main() 
    {
        auto v = std::vector { 1, 2 };
        std::initializer_list i;
        auto it = std::begin(i);
        *it = begin(v); // error: read-only variable is not assignable
    }
    

    Live Example

    If you look at the Standard Containers, in addition to accepting std::initializer_list in their constructors / inserters, they all have constructors / inserters taking an iterator pair, and the implementation is likely to delegate the initializer_list function to the corresponding iterator pair function. E.g. the std::vector::insert function in libc++ is this simple one-liner:

     iterator insert(const_iterator __position, initializer_list __il)
            {return insert(__position, __il.begin(), __il.end());}
    

    You should modify your code along similar lines:

    void someThing(std::initializer_list items)
    {
        someThing(items.begin(), items.end()); // delegate
    }
    
    template
    void someThing(It first, It last)
    {
        for (auto it = first, it != last; ++it) // do your thing
    }
    

    In times when you have your items in a vector instead of a literal list:

    std::vector v = { 1, 2 };
    auto i = { 1, 2 };
    someThing(begin(v), end(v)); // OK
    someThing(i); // also OK
    someThing({1, 2}); // even better
    

提交回复
热议问题