【问题标题】:Template type defined array initialisation模板类型定义数组初始化
【发布时间】:2013-10-30 23:40:40
【问题描述】:

我有一个数组,我想根据模板参数将其初始化为 constexpr(我认为这需要 c++14,因为我设想答案需要将初始化列表作为 constexpr)。

假设我有一个模板

template<T t>

在哪里

 T = int[1][2][3]

现在,我可以使用 type_traits std::extent 递归提取数组大小

我最终想做的是生成一个 constexpr 成员,其中 T 的维度作为 myarray 的元素

std::array<int,3> myarray = {1,2,3};

我已经看到了使用可变参数模板初始化数组的好方法 参考:How to construct std::array object with initializer list?

问题是,如何在给定 T 的情况下生成具有 T 维度的初始化列表或可变参数模板?1

【问题讨论】:

  • @R.MartinhoFernandes:我更喜欢在输入内容并希望它能够编译之前先动脑筋。由于我无法解决问题,我 a) 阅读了很多互联网,包括 stackoverflow 然后 b),发布了一个明确的问题,将我的问题作为一个最小示例。这还不够吗?

标签: c++ arrays templates constexpr c++14


【解决方案1】:

以下内容有点复杂,但应该可以(使用 C++11):

#include <array>
#include <type_traits>

template<std::size_t...> struct seq {};

template<typename,typename> struct cat;
template<std::size_t... Is, std::size_t... Js>
struct cat<seq<Is...>,seq<Js...>>
{
    using type = seq<Is...,Js...>;
};

template<typename> struct extract_seq { using type = seq<>; };
template<typename T,std::size_t N>
struct extract_seq<T[N]>
{
    using type = typename cat< seq<N>, typename extract_seq<T>::type >::type;
};

template<typename T> struct extract_type { using type = T; };
template<typename T,std::size_t N>
struct extract_type<T[N]>
  : extract_type<T>
{};

template<typename,typename> struct to_array_helper;
template<typename T, std::size_t... Is>
struct to_array_helper<T,seq<Is...>>
{
    constexpr static const std::array<T,sizeof...(Is)> value {{ Is... }};
};

template<typename T, std::size_t... Is>
constexpr const std::array<T,sizeof...(Is)>
to_array_helper<T,seq<Is...>>::value;

template<typename T>
struct to_array
  : to_array_helper<typename extract_type<T>::type,
                    typename extract_seq<T>::type>
{};

int main()
{
    auto arr = to_array< int[1][2][3] >::value;
}

Live example

【讨论】:

  • 我不确定我是否完全掌握了这个问题(累),但like this 不是更简单一点吗?
  • (或者that,可能更灵活一点)
  • @DyP 不错,尽管您在 to_array&lt;int, int[1][2][3]&gt; 中重复了 int,但您的版本要容易得多。但这可以很好地集成,请参阅here
  • 那是部分故意的。我想到了第二条评论中的解决方案,您可以在其中指定返回类型;以某种方式指定数组的元素类型是第一步。
  • @DyP 我明白了,当我试图专注于 OP 的需求时,您正在寻求更通用的解决方案。不管怎样,他现在应该有很多代码可以玩了。 :)
【解决方案2】:

我认为你不需要任何特殊的未来 C++。这在 C++11 中运行良好:

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

#include <prettyprint.hpp>

template <typename T>
struct Foo
{
    std::array<std::size_t, std::rank<T>::value> a;

    Foo() : Foo(X<std::rank<T>::value>(), Y<>(), Z<T>()) { }

private:
    template <unsigned int K>  struct X { };
    template <unsigned int ...I> struct Y { };
    template <typename> struct Z { };

    template <typename U, unsigned int K, unsigned int ...I>
    Foo(X<K>, Y<I...>, Z<U>)
    : Foo(X<K - 1>(),
          Y<I..., std::extent<U>::value>(),
          Z<typename std::remove_extent<U>::type>())
    { }

    template <typename U, unsigned int ...I>
    Foo(X<0>, Y<I...>, Z<U>) 
    : a { I... }
    { }
};

int main()
{
    Foo<char[4][9][1]> x;
    std::cout << x.a << std::endl;
}

输出:

[4, 9, 1]

【讨论】:

  • 这会计算维度,但不会返回维度本身。例如考虑 T = int[7][14][13]。所需的结果数组包含 7 14 13
  • @OllieB:哦,我明白了,我被你的例子甩了。嗯,也许在某处粘贴std::extent 可以解决这个问题。让我考虑一下。
  • @OllieB:在那里,已修复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-18
相关资源
最近更新 更多