使用相同的构造函数参数初始化所有元素或std :: array

时间:2018-03-16 10:21:50

标签: c++ templates

我想知道是否可以使用隐式删除的默认构造函数初始化std::array个对象,而不知道数组大小的先验,因为它是模板参数,因此具有失去了使用初始化列表的可能性。代码如下,它打破了对std::array<A, 3UL>&#34;

隐式删除的默认构造函数的调用
struct A {
  A (int b, int c) : mb(b), mc(c) { }
  int mb;
  int mc;
};

template <size_t NR_A>
struct B {
  B (int b, int c) : 
    // <- how to initialize mAs here?
  { }
  std::array<A, NR_A> mAs;
};

B<3> inst(1,1);

修改:我想将A的所有mAs初始化为A{1,1}

3 个答案:

答案 0 :(得分:4)

您可以使用委派构造函数和打包扩展

struct A {
    A(int b, int c) : b(b), c(c) { }
    A(const A&) = delete;
    A(A&&) = delete;
    int b;
    int c;
};

template <size_t N>
struct B {
  B (int b, int c) : B(b, c, std::make_index_sequence<N>{}) {}

  template<size_t... Is>
  B (int b, int c, std::index_sequence<Is...>) :
    arr{(Is, A{b, c})...}
  {}

  std::array<A, N> arr;
};

Live

请注意,如果删除了移动和复制构造函数,则只能在C ++ 17之后使用。

答案 1 :(得分:2)

对于C ++ 11和C ++ 14(即:pre-C ++ 17),你可以通过模板元编程实现你想要的东西。

您可以声明以下帮助程序类模板array_maker<>,该模板具有static成员函数模板make_array,它以递归方式调用自身:

template<typename T, std::size_t N, std::size_t Idx = N>
struct array_maker {
    template<typename... Ts>
    static std::array<T, N> make_array(const T& v, Ts...tail) {
        return array_maker<T, N, Idx-1>::make_array(v, v, tail...);
    }
};

然后,将此类模板专门用于Idx等于1的情况,即:递归的基本情况

template<typename T, std::size_t N>
struct array_maker<T, N, 1> {
    template<typename... Ts>
    static std::array<T, N> make_array(const T& v, Ts... tail) {
        return std::array<T, N>{v, tail...};
    }
};

最后,它可以通过这种方式在模板的构造函数中使用:

template <size_t NR_A>
struct B {
  B (int b, int c) : mAs{array_maker<A, NR_A>::make_array(A{b,c})}
  {}    
  std::array<A, NR_A> mAs;
};

答案 2 :(得分:1)

这是我想出的解决方案(需要c ++ 17)

template<typename T, std::size_t N, std::size_t index_t = N, typename... Ts>
constexpr auto make_array(T t, Ts... ts)
{
  if constexpr (index_t <= 1) {
    return std::array<T, N> {t, ts...};
  } else {
    return make_array<T, N, index_t - 1>(t, t, ts...);
  }
}

这是对以前具有阵列制造商结构的解决方案之一的修改。只是以更简洁的形式进行了同样的操作。

它接受一个项目,并在该项目上加倍,直到达到1的深度,然后从展开中返回一个数组。我没有意识到即使没有传递任何参数,您也可以使用fold表达式。尽管我从诸如printf之类的内容中暗中了解这一点。