简要描述;简介:

考虑用于存储整数值的基于可变参数模板的类型列表:

template<typename... Ts>
struct list {};

using my_int_list = list<std::integral_constant<0>,
                         std::integral_constant<1>,
                         std::integral_constant<2>>;


可以使用数组初始化程序和可变参数包扩展将其转储到数组中:

template<typename LIST>
struct to_array;

template<typename... Ts>
struct to_array<list<Ts...>>
{
    static constexpr unsigned int result[] = { Ts::value... };
};


现在考虑我想对2d数组做同样的事情(换句话说,输入是类型列表的类型列表)。我们可以使用后面的元函数来转储子数组,并使用第二个元函数来转储外部数组:

template<typename LIST>
struct to_2d_array;

template<typename... Ts>
struct to_2d_array<list<Ts...>>
{
    using value_type = unsigned int; //To simplify things, suppose we know the type
                                     //of the elements. Also suppose the array is
                                     //squared.

    static constexpr value_type result[sizeof...(Ts)][sizeof...(Ts)] = { to_array<Ts>::result... };
};


我的问题(即深度上下文):

我正在编写一个编译时的Mandelbrot分形渲染。渲染工作为“ fine” 1,它以RGB值的方形2d类型列表(相同长度的类型列表的类型列表)返回结果。
需要to_2d_array元函数将结果转储到数组中,并在运行时将其写入PPM文件中。

The RGB values是等同于std::integral_constant<unsigned int>的整数包装的实例,它具有保存该值的成员value

我上面发布的代码正是我使用标准类型(std::integral_constant)而不是我自己的类型编写的in my implementation。上面的代码在at coliru上运行完美,但是我的编译器(GCC4.8.1)说:


  初始化程序需要用附加的括号括起来。


to_2d_array中。如果我放了多余的花括号,则配准编译将失败,并显示“从指针到数组的无效转换”。

我做错了什么?是否有另一种近似方法可以实现这一目标?

[1]确实现在不起作用,因为此模板元编程怪物的编译会导致GCC内部分段错误:)。但是这个问题与问题无关...

最佳答案

根据您coliru example中写的内容,我想指出一些问题。


result的类型。

以下代码无法编译。

int main() {
  int x[] = {1, 2, 3};
  int y[3][3] = {x, x, x};
}


而以下是。

#include <array>

int main() {
  std::array<int, 3> x = {1, 2, 3};
  std::array<std::array<int, 3>, 3> y = {x, x, x};
}


resultto_array<>to_2d_array<>的类型与第一个示例等效。
result被声明为static constexpr,但是缺少脱机定义。


以下是经过修改以解决上述问题的代码。

#include <array>
#include <iostream>
#include <type_traits>

template <typename... Ts>
struct list {};

template <typename List>
struct to_array;

template <typename... Ts>
struct to_array<list<Ts...>> {

    using result_type = std::array<unsigned int, sizeof...(Ts)>;

    /* Use std::array<> instead of C-array. */
    static constexpr result_type result = { Ts::value... };

};  // ToArray<List<Ts...>>

/* Out-of-line definition for static constexpr variable. */
template <typename... Ts>
constexpr typename to_array<list<Ts...>>::result_type
    to_array<list<Ts...>>::result;

template <typename List>
struct to_2d_array;

template <typename... Ts>
struct to_2d_array<list<Ts...>> {

    using result_type =
        std::array<std::array<unsigned int, sizeof...(Ts)>, sizeof...(Ts)>;

    /* Use std::array<> instead of C-array. */
    static constexpr result_type result = { to_array<Ts>::result... };
};

/* Out-of-line definition for static constexpr variable. */
template <typename... Ts>
constexpr typename to_2d_array<list<Ts...>>::result_type
    to_2d_array<list<Ts...>>::result;

int main() {
  using my_int_list = list<std::integral_constant<int, 0>,
                           std::integral_constant<int, 1>,
                           std::integral_constant<int, 2>>;
  for (int i = 0; i < 3; ++i) {
    std::cout << to_array<my_int_list>::result[i] << ' ';
  }  // for
  std::cout << std::endl << std::endl;
  using my_2d_list = list<my_int_list,my_int_list,my_int_list>;
  /* Actually try printing the result. */
  for (int i = 0; i < 3; ++i) {
    for (int j = 0; j < 3; ++j) {
      std::cout << to_2d_array<my_2d_list>::result[i][j] << ' ';
    }  // for
    std::cout << std::endl;
  }  // for
}


印刷品:

0 1 2

0 1 2
0 1 2
0 1 2


使用gcc 4.8.2,clang 3.3和在Coliru上的任何gcc 4.8进行了测试。

07-28 02:54
查看更多