简体   繁体   中英

Is it not possible to convert a std::vector<T> to an std::initializer_list<T>?

I would have thought that one could do this? Yet, it doesn't seem to be the case. Why? Or am I doing something wrong?

#include <vector>
#include <initializer_list>
#include <iostream>

using namespace std;

void fn(std::initializer_list<int> i)
{
  for(int ivalue:i)
  {
    cout << ivalue << endl;
  }
}

int main()
{
  fn({1,2,3});
  fn(vector<int>{4,5,6})
  return 0;
}

demo

The reason I ask this is because I have a class that takes an initializer list and I've derived from it but need to massage the initializer list prior to passing it to the base. How can I accomplish this?

Sometimes the old ways are the best ways: just pass in the range:

void fn(std::initializer_list<int> i) {
    fn(i.begin(), i.end());
}

template <typename It>
void fn(It it, It end) {
    for (; it != end; ++it) {
        std::cout << *it << std::endl;
    }
}

fn({1, 2, 3});

std::vector<int> v{1, 2, 3};
fn(std::begin(v), std::end(v));

For your specific question... Your constructor that takes the initializer list has to iterate over it anyway, just delegate that operation to an iterator-pair constructor:

Foo(std::initializer_list<T> init)
: Foo(init.begin(), init.end())
{ }

template <typename It>
Foo(It it, It end)
{
    // here the magic happens
}

C++ lacks a simple "view into a contiguous block of memory" class. Here is one:

template<class T>
struct ro_array_view {
  T const* b_ = nullptr;
  T const* e_ = nullptr;
  size_t size() const { return end()-begin(); }
  T const* begin() const { return b_; }
  T const* end() const { return e_; }
  T const& operator[](size_t i)const{ return begin()[i]; }
  bool empty()const{return begin()==end();}
  T const& front() const { return *begin(); }
  T const& back() const { return *std::prev(end()); }

  // annoying numbers of constructors:
  struct from_container_tag {};
  template<class O>
  ro_array_view( from_container_tag, O&& o ):
    ro_array_view(o.data(), o.size()) {}

  template<class...A>
  ro_array_view( std::vector<T,A...> const& o )
    :ro_array_view(from_container_tag{},o) {}
  ro_array_view( std::initializer_list<T> const& il )
    :ro_array_view(il.begin(), il.size()) {}
  template<size_t N>
  ro_array_view( std::array<T, N> const& o )
    :ro_array_view(from_container_tag{},o) {}
  template<size_t N>
  ro_array_view( std::array<T const, N> const& o )
    :ro_array_view(from_container_tag{},o) {}
  template<size_t N>
  ro_array_view( T const(&arr)[N] )
    :array_view( arr, N ) {}

  // penultimate constructor of most paths:
  ro_array_view( T const* arr, size_t N )
    :ro_array_view(arr, arr+N) {}
  // terminal constructor:
  ro_array_view( T const* b, T const* e )
    :b_(b),e_(e) {}
};

now simply take an ro_array_view<int> and it will convert the incoming argument to a pair of pointers, and expose a read-only container-like interface to it.

This seems overkill at first glance, but you'll find it is a very common function to use. A huge chunk of functions that take a std::vector<T> const& should instead take a ro_array_view<T> by value.

A non- ro_array_view is a bit different (its methods are all mostly const still, but it stores T* not T const* . I'd call it rw_array_view , then make array_view a using alias that conditionally uses ro_array_view or rw_array_view . Add in a converting ctor from rw_array_view to ro_array_view to finish up the project.

I have two different types, instead of one, because rw_array_view and ro_array_view have different constructors from some container. a rw_array_view<T> can be constructed from a vector<T,A...>& , while a ro_array_view<T> requires vector<T, A...>const& . std::array is a bit worse because const T is a valid type to have in a std::array . And ro_array_view is used in most uses, with rw_array_view being useful for cases where we want to modify the contents without modifying the container.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM