在构造函数中初始化私有 std::array 成员



我想知道当初始数组值是构造函数的参数时,在构造函数中初始化类的std::array成员的正确方法是什么?

更具体地说,请考虑以下示例:

class Car {
public:
Car(const std::string& color, int age): color_(color), age_(age) {}
// ...
private:
std::string color_;
int age_;
};
class ThreeIdenticalCars {
private:
std::array<Car, 3> list;
public:
ThreeIdenticalCars(const std::string& color, int age):
// What to put here to initialize list to 3 identical Car(color,age) objects?
{}
};

显然一种方法是写list({Car(color,age), Car(color,age), Car(color,age)}),但是如果我们想要 30 辆相同的汽车而不是三辆,这显然无法扩展。

如果我没有使用std::arraystd::vector解决方案将是list(3, Car(color,age)(或list(30, Car(color, age))但在我的问题中,列表的大小是已知的,我认为使用std:array更正确。

数组版本的一个选项是使用模板函数来构建数组。您必须进行测试以查看它是否在发布模式下被优化或复制,

#include <iostream>
#include <array>
#include <tuple>
class Car {
public:
Car(const std::string& color, int age): color_(color), age_(age) {}
// ...
//private:
std::string color_;
int age_;
};
template <typename CarType, typename... Args ,size_t... Is>
std::array<CarType,sizeof...(Is)> make_cars(std::index_sequence<Is...>,Args&&... args )
{
return { (Is,CarType(args...))... };
}
class ThreeIdenticalCars {
//private:
public:
std::array<Car, 3> list;
//public:
ThreeIdenticalCars(const std::string& color, int age) : 
list(make_cars<decltype(list)::value_type>(
std::make_index_sequence<std::tuple_size<decltype(list)>::value>(),
color,
age
))
{}
};
int main()
{
ThreeIdenticalCars threecars("red", 10);
for(auto& car : threecars.list)
std::cout << car.color_ << " " << car.age_ << std::endl;
return 0;
}

演示

rmawatson的好答案。

这是一个类似的替代方案,它尝试了 2 项增强功能:

  1. 按模型施工。
  2. 复制模型 N-1 次并将最后一个移动到位。

当然,它要求汽车是可复制的。

#include <array>
#include <string>
class Car {
public:
Car(const std::string& color, int age): color_(color), age_(age) {}
// ...
private:
std::string color_;
int age_;
};
namespace detail
{
template<std::size_t...Is, class Model>
auto build_array_impl(std::index_sequence<Is...>, Model&& model)
{
constexpr auto size = sizeof...(Is) + 1;
return std::array<std::decay_t<Model>, size>
{
// N-1 copies
(Is, model)...,
// followed by perfect forwarding for the last one
std::forward<Model>(model)
};
}
}
template<std::size_t N, class Type>
auto build_array(std::integral_constant<std::size_t, N>, Type&& model)
{
return detail::build_array_impl(std::make_index_sequence<N-1>(), 
std::forward<Type>(model));
}
class ThreeIdenticalCars {
private:
static constexpr auto num_cars = std::size_t(3);
static constexpr auto num_cars_c = std::integral_constant<std::size_t, num_cars>();
std::array<Car, num_cars> list;
public:
ThreeIdenticalCars(const std::string& color, int age)
: list(build_array(num_cars_c, Car(color, age)))
{}
};
int main()
{
ThreeIdenticalCars tic("red", 1);
}

最新更新