【问题标题】:What are constexpr containers in C++17?什么是 C++17 中的 constexpr 容器?
【发布时间】:2019-10-25 15:28:36
【问题描述】:

我想创建一个具有std::map 之类的方法的类,但它应该在编译时进行排序。哪些constexpr 容器适合存储键template<class K> 和值template<class V>

std::vector 不符合这些要求。

UPD:我们发现std::array 有很多 constexpr 方法。我的问题使用std::array<std::pair<K, V> > 就足够了。 但问题仍然存在。

【问题讨论】:

  • 所以听起来您正在寻找类似 @​​987654327@ 的东西,一个 constexpr 函数来从初始化列表创建预排序,以及一些额外的函数来根据特定字段进行查找的元素(用于排序的相同字段)?
  • @liliscent:如果有递归定义,代码中的生成是很自然的。
  • @BenVoigt 使用编译时计算来计算数据(矩阵)真的很疯狂 IMO。我宁愿用 Python 计算它们并将其复制到源代码中。
  • @liliscent:那只意味着你更喜欢 python 而不是 C++。这并不意味着世界其他地方也需要这样做。
  • 我也喜欢模板编程,但这里我想说的是纯数据的计算,比如矩阵。我认为在没有实际收益的情况下减慢编译速度是不值得的。从文件加载数据是正确的选择。 @克里斯

标签: c++ templates constexpr


【解决方案1】:

大多数 C++ 标准库容器不能用作 constexpr。 AFAIK 只有 std::bitsetstd::array(任意长度)的前 64 位是可填充的编译时间。

在程序本身准备好之前,不要专注于此类性能优化。在 C++11 中使用可变参数模板函数填充大的 std::array 编译时间并不难。

如何使用可变参数模板填充 4 个整数数组(每个代表 6 种颜色之一)编译时间的示例:

constexpr int ColorCount = 6;
constexpr int PositionCount = 4;

using Positions = std::array<int, PositionCount>;

template <int N>
struct PositionsFiller
{
    template <typename T, typename ...Tn>
    static constexpr Positions fill(T packed, Tn ...rest)
    {
        return PositionsFiller<N - 1>::fill(packed / ColorCount, packed % ColorCount, rest...);
    }
};

template <>
struct PositionsFiller<1>
{
    template <typename T, typename ...Tn>
    static constexpr Positions fill(T last, Tn ...rest)
    {
        return Positions{last, rest...};
    }
};

constexpr Positions pos666(PositionsFiller<PositionCount>::fill(666));

在 C++17 中,同样可以通过简单的循环来完成,因为对 constexpr 的要求很宽松,并且不需要可变参数模板:

constexpr int ColorCount = 6;
constexpr int PositionCount = 4;

using Positions = std::array<int, PositionCount>;

static constexpr Positions fillPositions(int packed)
{
    Positions ret{};
    for (Positions::size_type i = ret.size(); i > 0; --i)
    {
        ret[i-1] = packed % ColorCount;
        packed /= ColorCount;
    }
    return ret;
}

constexpr Positions pos666(fillPositions(666));

请注意,编译时进行复杂的准备工作会减慢编译速度。当模块仍在开发中时,这可能很烦人。更好的是在程序开始时填充通常的可变数组,然后用编译时填充等优化替换它。

【讨论】:

  • 在具有任意数量元素的 constexpr 函数中使用 std::array 没有任何问题。这将包括像 make_sorted_array 这样的想法,它允许将元素作为参数传递并返回排序的数组对象。甚至像树一样的 std::map 也应该可以使用元组作为内存分配器来实现。 (从未尝试过元组分配器,但基本思想似乎适用于任何类似 constexpr stl 的容器)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-28
  • 1970-01-01
  • 2017-12-24
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 2018-02-10
相关资源
最近更新 更多