为什么不是std :: algorithms constexpr,哪些可能是?

时间:2015-09-04 10:08:00

标签: c++ algorithm c++14 constexpr

为什么没有任何std::algorithm方法constexpr?如果我正确理解新的C ++ 14规则,其中许多方法可能是constexpr。例如,为什么std::find可以constexpr

static constexpr std::array<char, 4> DnaBases {'A', 'C', 'G', 'T'};

constexpr bool is_dna(char b)
{
    return std::find(std::cbegin(DnaBases), std::cend(DnaBases), b) != std::cend(DnaBases); // why not?
}

其他std::algorithm可能是constexpr

5 个答案:

答案 0 :(得分:13)

它可能是Marquee,但不能作为常量表达式进行求值,因为在这种情况下,例如对于编译时查找,需要: constexpr应该是constexpr,迭代器的begin/end应该是constexpr,* operator应该是constexpr,operator ==对于迭代器应该是constexpr,operator !=用于迭代器应该是constexpr。但是,如果所有函数都是operator ++,则可以使用constexpr实现许多算法。

您可以查看SPROUT library以了解constexpr容器/算法的实现。

关于isocpp.org forums

的相关谈话

答案 1 :(得分:11)

根据constexpr - ness,不能重载函数。因此,任何定义为constexpr的函数都需要以constexpr的形式实现。此要求对所有实施都施加了约束。

与C ++ 11相比,C ++ 14规范在约束方面有所放松。但是,当规范最终确定时,没有人确信当算法被强制为constexpr时,可以实现在没有constexpr约束的情况下可以实现的所有优化。如果不强制要求constexpr实施不阻碍非constexpr功能,则算法将不会被定义为constexpr。算法的非constexpr使用仍被认为是算法的主要用途。

可能值得拥有一组特殊的算法,这些算法被定义为constexpr。我不知道有一个相应的提议。如果需求保证标准化,我也​​没有看到很多,但我的看法可能与其他人不同。

答案 2 :(得分:6)

当前(C ++ 14)标准库是pretty much under-powered w.r.t.关于constexpr的相应核心语言能力。

,例如,MSVC 2015,它仅对constexpr提供C ++ 11语言支持,could almost fully implement constexpr的整个C ++ 14标准库使用。唯一的例外是std::minstd::maxstd::minmaxstd::min_elementstd::max_elementstd::minmax_element std::initializer_list

从C ++ 1z(17?)开始,std::xxx_element算法将成为常规迭代器和比较器输入的constexpr算法,以统一std::initializer_list的用法。此外,C ++ 1z还有proposals for constexpr lambda个函数。

随着lambdas的升级,仍然存在一些核心语言限制,以防止整个<algorithm>标题变为constexpr。 (请注意,这些不是硬核技术障碍,most of them could be resolved允许编译器对它们进行评估。)

  1. 某些算法可以通过调用std::get_temporary_buffer std::inplace_merge std::stable_sortstd::stable_partitionconstexpr来动态分配内存,这在memset上下文中是不允许的。
  2. 某些算法可以回退到std::fillstd::fill_nconstexpr)等低级C例程,这些例程会阻止图书馆作者在goto上下文中使用这些算法
  3. 有些算法实施可以从明智地使用std::nth_element(例如std::stable_sortconstexpr)中受益,C++1z proposal被拒绝。
  4. 最后但同样重要的是,constexpr是一个接口更改,承诺所有未来的实现都必须实现这一承诺。因此,不允许实现将noexcept添加为实施质量功能(与constexpr相反)。
  5. 特别是第4个问题阻碍了实验,可以为标准库(算法,容器和其他实用程序)推送多少constexpr。相反,必须为return function() { // statement 1 // statement 2 return result; } 的每次扩展编写并批准单独的提案。

答案 3 :(得分:2)

这是Antony Polukhin的提案P0202的主题:

Add Constexpr Modifiers to Functions in and Headers

我希望C ++ Library Evolution Working Group能够采用它并进入C ++ 20。

答案 4 :(得分:0)

std::algorithm算法作用于迭代器。有一个技术上的原因,为什么使它们constexpr通常会阻止编译它们(在C ++ 11中)或什么也不做(在C ++ 14中或使用条件 - constexpr),但也有一个语义原因为什么它们没有意义constexpr

技术原因constexpr函数无法调用非constexpr表达式。 ForEveR指出,如果模板constexpr函数调用非constexpr表达式,则无法在编译时对其进行求值。

对于std::algorithm,评估constexpr中的std::algorithm函数将要求访问容器迭代器的函数为constexpr,这反过来又要求迭代器本身是constexpr类型。但这几乎是不可能的定义;容器通常被设计为对堆分配的内存的轻量访问,但是在编译时(当然)不能分配堆内存。在下面的注释中,dyp指出迭代器并不总是指向容器,但即使这些迭代器也不可能在编译时使用;例如,stream对象当然在编译时不可读或不可写,因为IO不能在编译时完成。

这会导致语义问题: constexpr在语义上意味着函数可以在编译时进行评估。有条件地声明函数 - constexpr不可能在编译时评估它们时会使API混乱和误导。

现在,我认为如果有一种方法可以在编译时创建和使用容器,那么语言会得到改进; 这会使constexpr与Lisp的宏功能更加相似。这可能最终会被添加,但目前现有的标准库代码并不支持它。如上所述,最灵活的方法是允许某些对象在编译时期间存在于堆上,但核心语言根本不支持它,并且会产生一些严重的复杂性。例如,用这些对象是什么合法的?要么它们的生命周期只需要限制在编译时间,要么它们需要作为静态const存储器包含在最终程序中(如字符串文字),或者......什么?