为什么没有任何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
?
答案 0 :(得分:13)
它可能是Marquee
,但不能作为常量表达式进行求值,因为在这种情况下,例如对于编译时查找,需要:
constexpr
应该是constexpr,迭代器的begin/end
应该是constexpr,* operator
应该是constexpr,operator ==
对于迭代器应该是constexpr,operator !=
用于迭代器应该是constexpr。但是,如果所有函数都是operator ++
,则可以使用constexpr
实现许多算法。
您可以查看SPROUT library以了解constexpr容器/算法的实现。
的相关谈话答案 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::min
,std::max
,std::minmax
,std::min_element
,std::max_element
,std::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允许编译器对它们进行评估。)
std::get_temporary_buffer
std::inplace_merge
std::stable_sort
,std::stable_partition
和constexpr
来动态分配内存,这在memset
上下文中是不允许的。 std::fill
(std::fill_n
和constexpr
)等低级C例程,这些例程会阻止图书馆作者在goto
上下文中使用这些算法std::nth_element
(例如std::stable_sort
,constexpr
)中受益,C++1z
proposal被拒绝。constexpr
是一个接口更改,承诺所有未来的实现都必须实现这一承诺。因此,不允许实现将noexcept
添加为实施质量功能(与constexpr
相反)。 特别是第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存储器包含在最终程序中(如字符串文字),或者......什么?