【问题标题】:Dump variadic template content to a 2D array将可变参数模板内容转储到二维数组
【发布时间】:2013-10-02 23:37:14
【问题描述】:

简要说明:

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

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... };
}; 

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

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 分形渲染。渲染工作“正常”1,并将结果作为 RGB 值的方形 2d 类型列表(相同长度的类型列表的类型列表)返回。 需要to_2d_array 元函数将结果转储到数组并在运行时将其写入 PPM 文件中。

The RGB values 是等效于std::integral_constant&lt;unsigned int&gt; 的完整包装器的实例,它有一个成员value 保存该值。

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

初始化器需要用额外的大括号括起来。

to_2d_array。如果我放了额外的大括号,则赋值编译会失败,并出现“从指针到数组的无效转换”。

我做错了什么?是否有其他近似值可以实现这一目标?

[1] 现在真的不行,因为编译这个模板元编程怪物会导致 GCC 内部分段错误 :)。但是这个问题和问题无关……

【问题讨论】:

  • 您向我们展示了有效的代码,但您没有展示不起作用的代码。请编辑您的问题并添加它。
  • @DanielFrey 我提供的代码完全相同,但是使用标准库的类型(即每个人都知道的类型)而不是我自己的类型。
  • @DanielFrey 您也可以查看原始代码here(第 64 行及以下)
  • 它似乎工作here
  • @DanielFrey 你试过二维类型列表吗?在该示例中,您使用了 1d 类型列表

标签: c++ arrays c++11 template-meta-programming typelist


【解决方案1】:

根据您的coliru example 中写的,我想指出几个问题。

  1. 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};
    }
    

    to_array&lt;&gt;to_2d_array&lt;&gt;result的类型与第一个例子等价。

  2. 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 进行测试。

【讨论】:

    猜你喜欢
    • 2011-10-26
    • 2021-06-04
    • 1970-01-01
    • 2014-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    相关资源
    最近更新 更多