是不是可以将std :: vector <t>转换为std :: initializer_list <t>?</t> </t>

时间:2015-01-22 20:25:01

标签: c++ c++11 vector stdvector initializer-list

我原本以为人们可以做到这一点?然而,事实似乎并非如此。为什么?或者我做错了什么?

#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

我之所以这样问是因为我有一个类,它带有一个初始化列表并且我从中派生出来但需要在将初始化列表传递给基础之前按下它。我怎么能做到这一点?

2 个答案:

答案 0 :(得分:2)

有时旧的方式是最好的方法:只需通过范围:

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

对于您的具体问题......无论如何,获取初始化列表的构造函数必须迭代它,只需将该操作委托给迭代器对构造函数:

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

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

答案 1 :(得分:0)

C ++缺少一个简单的“查看连续的内存块”类。这是一个:

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

现在只需要一个ro_array_view<int>,它会将传入的参数转换为一对指针,并向它公开一个只读的容器式接口。

乍一看这似乎有点过头了,但你会发现它是一个非常常见的功能。采用std::vector<T> const&的大量函数应该取值为ro_array_view<T>

ro_array_view有点不同(其方法大部分都是const,但它存储T*而不是T const*。我称之为{{} 1}},然后使rw_array_view成为有条件地使用array_viewusing的{​​{1}}别名。添加从ro_array_viewrw_array_view的转换代码完成项目。

我有两种不同的类型,而不是一种,因为rw_array_viewro_array_view具有与某个容器不同的构造函数。可以使用rw_array_view构建ro_array_view,而rw_array_view<T>则需要vector<T,A...>&ro_array_view<T>有点差,因为vector<T, A...>const&std::array中的有效类型。 const T用于大多数用途,std::array对于我们想要修改内容而不修改容器的情况非常有用。