c++ - 为递归定义的类数组类模拟聚合初始化

标签 c++ initialization c++17 list-initialization

考虑:

template <std::size_t r,std::size_t d>
struct Tensor
{
  Tensor<r-1u,d> Data[d];
};

template <std::size_t d>
struct Tensor<0u,d>
{
  double Data;
};

我们可以使用 copy-list-initialization 以这种方式初始化这样的 Tensor:

Tensor<2u,3u> t= { 1.0, 2.0, 3.0,
                   4.0, 5.0, 6.0,
                   7.0, 8.0, 9.0 };

注意大括号省略。

这也适用于通用编程上下文,例如:

template <typename... T,
  typename= std::enable_if_t<(std::is_same_v<T,double> && ...) && (sizeof...(T)==9u)>>
Tensor<2u,3u> MakeTensor(T... x) { return {x...}; }

但是,如果 Data 是私有(private)的,Tensor 将不再是聚合,因此上述语法将无效。

在那种情况下,是否可以通过编程方式恢复此行为?

最佳答案

聚合初始化只适用于聚合,所以不,严格来说,这是不可能的。

您可以通过提供 initializer_list/variadic 模板构造函数或通过仅出于初始化目的采用张量数据结构的聚合版本的构造函数来模拟它,例如:

template <std::size_t r,std::size_t d>
struct RawTensor
{
  std::array<RawTensor<r-1u,d>,d> data;
};

template <std::size_t d>
struct RawTensor<0u,d>
{
  double data;
};

template <std::size_t r,std::size_t d>
struct Tensor
{
  Tensor( RawTensor<r,d> const& data ): data_{data}{}

private:
  RawTensor<r,d> data_;
};

template <typename... T,
typename= std::enable_if_t<(std::is_same_v<T,double> && ...) && (sizeof...(T)==9u)>>
RawTensor<2u,3u> MakeTensor(T... x) { return {x...}; }

Tensor<2u,3u> t1 = RawTensor<2u,3u>{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
Tensor<2u,3u> t2 = MakeTensor( 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 );

并让编译器对其进行优化。如果您的初衷是利用 operator[] 的链接(因此您需要嵌套数据为 Tensor 类型),它仍然是可能的,但需要不那么琐碎的初始化逻辑。

关于c++ - 为递归定义的类数组类模拟聚合初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47133445/

相关文章:

c++ - 在 X 轴上翻转 QGraphicsItem "inplace"(左/右)

c++ - 列出构造函数初始化中的评估顺序

C++ static struct init - 项目没有命名类型

Swift - 动态初始化嵌套结构

c++ - 当目标指针不是基类的类型时,为什么允许dynamic_cast为多态类生成空指针?

c++ - 在非常量上下文中使用 std::size

c++ - 是否有任何巧妙的方法可以从数组 vector 中获取指向数据的指针?

c++ - 如果不存在,则调用自由函数而不是方法

C 在数组初始化器中初始化指向数组的指针

c++ - 有哪些使用 PostgreSQL 以 C/C++ 编写的开源应用程序?