简体   繁体   English

如何在类的初始化列表中初始化 std::array 而不对数组的大小进行硬编码

[英]How to initialize an std::array in the initializer list of a class without hardcoding the array's size

I've got Foo.h:我有 Foo.h:

#include <array>

class Bar {
public:
  Bar(std::string name) : name(name) {}

  std::string name;

};

class Foo {
public:
  enum {ARRAY_SIZE=10};

  Foo();

  void printElement(int idx);

  std::array<Bar,ARRAY_SIZE> myArray;

};

Foo.cc: foo.cc:

#include "Foo.h"
#include <iostream>

Foo::Foo(): myArray({Bar("9"),Bar("8"),Bar("7"),Bar("6"),Bar("5"),
                     Bar("4"),Bar("3"),Bar("2"),Bar("1"),Bar("0")}) {}


void Foo::printElement(int idx) {
  if (idx < ARRAY_SIZE) {
    std::cout << "Value is " << myArray[idx].name << std::endl;
  } else {
    std::cout << "Index out of bounds" << std::endl;
  }
}

int main() {
  Foo foo;
  foo.printElement(1);
}

The problem is that the {Bar("9"),Bar("8"),Bar("7"),Bar("6"),Bar("5"),Bar("4"),Bar("3"),Bar("2"),Bar("1"),Bar("0")} is too literal, I need to be able to use an expression which expands to the right size based on the value of ARRAY_SIZE (which could live in an external header file).问题是{Bar("9"),Bar("8"),Bar("7"),Bar("6"),Bar("5"),Bar("4"),Bar("3"),Bar("2"),Bar("1"),Bar("0")}太字面意思了,我需要能够使用一个表达式,根据ARRAY_SIZE(可以存在于外部头文件中)。

Note that in this example I must initialize myArray in the initializer list, otherwise I get this:请注意,在此示例中,我必须在初始化列表中初始化myArray ,否则我会得到:

(...)/gcc/6.3.0/include/c++/6.3.0/array:90:12: error: no matching function for call to 'Bar::Bar()'

What's the best way to do it?最好的方法是什么?

I'm using g++ 6.3.0 by the way.顺便说一下,我正在使用 g++ 6.3.0。

Use a helper function.使用辅助函数。 Add添加

template <std::size_t N>
auto make_array()
{
    std::array<Bar, N> arr;
    for (std::size_t i = 0; i < N; ++i)
        arr[i] = std::to_string(N - i - 1);
    return arr;
}

To your class and then you can use it in the member initializer list like到您的班级,然后您可以在成员初始值设定项列表中使用它,例如

Foo::Foo(): myArray(make_array<10>()) {}

This only works through if Bar is default constructable.这仅适用于Bar是默认可构造的。

For your code what you can do is add another helper that has a std::index_sequence of values to construct the Bar 's from and that would look like对于您的代码,您可以做的是添加另一个具有std::index_sequence值的帮助程序来构造Bar的来源,看起来像

// helpers for reversing an integer sequence
template <std::size_t ... Is>
constexpr auto indexSequenceReverse (std::index_sequence<Is...> const &)
   -> decltype( std::index_sequence<sizeof...(Is)-1U-Is...>{} );

template <std::size_t N>
using makeIndexSequenceReverse
   = decltype(indexSequenceReverse(std::make_index_sequence<N>{}));

class Bar {
public:
  Bar(std::string name) : name(name) {}

  std::string name;

};

class Foo {
public:
  enum {ARRAY_SIZE=10};

  Foo();

  void printElement(int idx);

  std::array<Bar,ARRAY_SIZE> myArray;

  // get sequence and expand out initializes 
  template <std::size_t ... Is>
  auto make_array_impl(std::integer_sequence<size_t, Is...>)
  {
      return std::array{ Bar{std::to_string(Is)}... };
  }

  // convenient forwarder to implementation
  template <std::size_t N>
  auto make_array()
  {
      return make_array_impl(makeIndexSequenceReverse<N>{});
  }

};

Foo::Foo(): myArray(make_array<10>()) {}

void Foo::printElement(int idx) {
  if (idx < ARRAY_SIZE) {
    std::cout << "Value is " << myArray[idx].name << std::endl;
  } else {
    std::cout << "Index out of bounds" << std::endl;
  }
}

int main() {
  Foo foo;
  foo.printElement(1);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在类的初始化器列表中初始化std :: vector - Initialize std::vector in class's initializer list 数组大小可变的模板类:使用数组引用或括号括起来的初始化程序列表进行初始化 - Template class with variable array size: initialize with array reference or brace-enclosed initializer list 如何在成员初始值设定项列表中初始化数组 - How to initialize an array in the member initializer list 如何使用初始化列表初始化数组元素? - How to initialize array elements by using initializer list? 如何从嵌套的std :: initializer_list初始化2D C样式数组? - How to initialize a 2D C-style array from a nested std::initializer_list? "如何在没有默认构造函数的情况下初始化类的 std::array?" - How can I initialize an std::array of a class without a default constructor? 如何在没有std :: initializer_list的情况下列出初始化模板化类的方法,使其具有固定的大小 - how to list initialise a templated class without std::initializer_list so it has a fixed size 在类的成员初始化器列表中初始化std :: tuple - Initialize std::tuple in member initializer list of a class 使用初始化列表初始化类中的std :: ofstream - Initialize a std::ofstream in a class using initializer list 如何让我的数组 class 实例使用初始化列表来初始化数组 - How can I get my array class instance to use initializer list to initialize the array
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM