Why aren't any std::algorithm
methods constexpr
? If I understand the new C++14 rules correctly, many of these methods could be constexpr
. For example, why can't std::find
be 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?
}
Which other std::algorithm
s could be constexpr
?
It could be constexpr
, but cannot be evaluated as a constant expression, since in this case, for example for compile-time find it is required that:
begin/end
should be constexpr, the * operator
of the iterator should be constexpr, operator ==
should be constexpr, operator !=
for the iterator should be constexpr, operator ++
for the iterator should be constexpr. But, if all functions are constexpr
, then many algorithms can be implemented with constexpr
.
You can look at the SPROUT library for the implementation of constexpr containers/algorithms.
And related talk on the isocpp.org forums
Functions cannot be overloaded based on constexpr
-ness. As a result, any function defined as constexpr
needs to be implemented in a form which could be a constexpr
. This requirement imposes constraints on all implementations.
The C++14 specification is somewhat relaxed with respect to the constraints compared to C++11. However, when the specification was finalized nobody was confident that all optimizations which can be achieved without the constexpr
constraint can be achieved when algorithms are mandated to be constexpr
. Without knowing that the non-constexpr
functionality is not impeded by mandating constexpr
implementations the algorithms won't be defined to be constexpr
. The non-constexpr
use of algorithms is still assumed to be the primary use of algorithms.
It may be worth having a special set of algorithms which are defined to be constexpr
. I'm not aware of a correspnding proposal. I also don't see a lot if demand warranting standardization but my perception may be different from other's.
The current (C++14) Standard Library is pretty much under-powered w.r.t. to the corresponding Core Language capabilities concerning constexpr
.
E.g., MSVC 2015, which only has C++11 language support for constexpr
, could almost fully implement the entire C++14 Standard Library usage of constexpr
. The only exceptions were std::min
, std::max
, std::minmax
, std::min_element
, std::max_element
, std::minmax_element
for std::initializer_list
.
As of C++1z (17?), the std::xxx_element
algorithms will become constexpr
algorithms for general iterator and comparator inputs to unify the usage for std::initializer_list
. Furthermore, there are proposals for constexpr
lambda functions for C++1z as well.
With lambdas being upgraded, there are still a few core language limitations left to prevent the entire <algorithm>
header from becoming constexpr
. (Note that these are not hard-core technological obstacles, most of them could be resolved by allowing the compiler to evaluate them).
- Some algorithms can dynamically allocate memory by calling
std::get_temporary_buffer
(std::inplace_merge
,std::stable_sort
andstd::stable_partition
) which is not allowed inconstexpr
contexts. - Some algorithms can fall back to low-level C routines such as
memset
(std::fill
andstd::fill_n
) that would prevent library authors from using these algorithms inconstexpr
contexts. - Some algorithm implementations can benefit from the judicious use of
goto
(e.g.std::nth_element
,std::stable_sort
), for which aC++1z
proposal was rejected. - Last but not least,
constexpr
is an interface change, promising that all future implementations will have to deliver this promise. For that reason, implementations are not allowed to addconstexpr
as a Quality of Implementation feature (in contrast tonoexcept
).
Especially the 4th issue stalls the experimentation with how much constexpr
could be pushed for the Standard Library (algorithms, containers and other utilities). Instead, a separate proposal has to be written and approved for every expansion of constexpr
.
This is the subject of Antony Polukhin's proposal P0202:
Add Constexpr Modifiers to Functions in and Headers
which I hope would be adopted by the C++ Library Evolution Working Group and make its way into C++20.
std::algorithm
algorithms act on iterators. There is a technical reason why making them constexpr
would usually either prevent compiling them (in C++11) or do nothing (in C++14 or with conditional-constexpr
), but there's also a semantic reason why it wouldn't make sense for them to be constexpr
.
The technical reason is that constexpr
functions cannot call non-constexpr
expressions. ForEveR points out that template constexpr
functions can't be evaluated at compile-time if they call non-constexpr
expressions.
In the case of std::algorithm
, evaluating constexpr
functions in std::algorithm
would require the functions for accessing container iterators to be constexpr
, which in turn would require the iterators themselves to be constexpr
types. But this is impossible almost by definition; containers are typically designed as lightweight access to heap-allocated memory, but heap memory cannot be allocated at compile time (of course). In the comments below, dyp points out that iterators don't always point to containers, but even these iterators are unlikely to be useable at compile-time; for instance, streams objects are of course not readable or writeable at compile time, since IO cannot be done at compile time.
This leads to the semantic problem: constexpr
semantically means that a function is intended to be possible to evaluate at compile time. Declaring functions conditionally-constexpr
when it is impossible to evaluate them at compile time would make the API confusing and misleading.
Now, I think the language would be improved if there were a way to create and use containers at compile time; this would make constexpr
that much more similar to Lisp's macro capabilities. This may eventually be added, but currently it's not really supported by existing standard library code. The most flexible approach, of allowing some objects to live on the heap during compile time, is, as mentioned above, not supported at all by the core language, and it would create some serious complications. For instance, what would it be legal to do with such objects? Either their lifetimes would need to be limited to compile-time only, or they would need to be included as static const memory in the final program (like a string literal), or...what?
来源:https://stackoverflow.com/questions/32395408/why-arent-stdalgorithms-constexpr-and-which-could-be