[英]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.