On 6/27/19 11:41 AM, Jonathan Wakely wrote:
On 26/06/19 19:13 -0400, Ed Smith-Rowland via libstdc++ wrote:
Here is the first of three patches for C++20 constexpr library.

?????? Implement C++20 p0202 - Add constexpr Modifiers to Functions in <algorithm> and <utility> Headers. ???? ??Implement C++20 p1023 - constexpr comparison operators for std::array.

I believe I have answered peoples concerns with the last patch attempts [https://gcc.gnu.org/ml/libstdc++/2019-03/msg00132.html].

The patch is large because of test cases but really just boils down to adding constexpr for c++2a.

I still have some concerns about the changes like:

?????? template<typename _Iterator, typename _Value>
+?????????? _GLIBCXX20_CONSTEXPR
?????????? bool
-?????????? operator()(_Iterator __it, _Value& __val) const
+?????????? operator()(_Iterator __it, const _Value& __val) const
?????????? { return *__it < __val; }

Make a type where operator< changes the rhs.?? I was thinking you'd want a compare to operate on const things but I guess we have to be ready for anything.?? I was also thinking < is left associative for a class member but i guess a class could have a thing that mutates the rhs too.?? Nothing got hit in any of my testing.?? If this is a thing we probably should make a general test for things like this somewhere.?? Maybe someone wants to log references or something.

1. I'll experiment to see if I really need these (I *thought* I did, but...)

2. If I still do then I'll make overloads?


I think that might change semantics for some types, and I haven't yet
figured out if we care about those cases or not. I'll try to come up
with some examples that change meaning.

This could use _GLIBCXX14_CONSTEXPR:

+?? /**
+???? * A constexpr wrapper for __builtin_memmove.
+???? * @param __num The number of elements of type _Tp (not bytes).

I don't think we want a Doxygen comment for this, as it's not part of
the public API. Just a normal comment is fine.

+???? */
+?? template<bool _IsMove, typename _Tp>
+?????? _GLIBCXX20_CONSTEXPR
+?????? inline void*
+?????? __memmove(_Tp* __dst, const _Tp* __src, size_t __num)
+?????? {
+#if __cplusplus > 201703L \
+?????? && defined(_GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED)
+?????????? if (__builtin_is_constant_evaluated())
+?????? {
+?????????? for(; __num > 0; --__num)
+?????????????? {
+?????????????????? if constexpr (_IsMove)
+?????????????? *__dst = std::move(*__src);
+?????????????????? else
+?????????????? *__dst = *__src;

Do we need this _IsMove condition here? We should only be using this
function for trivially copyable types, in which case copy vs move
shouldn't matter, should it?

Oh ... is it because we also end up using this __memmove function for
non-trivially copyable types, during constant evaluation? Hmm. Then
it's more than just a wrapper for __builtin_memmove, right? It's
"either memmove or constexpr range copy", or something.

Yup.?? I'm also bad at naming things.?? Furthermore, I expect the standards people to want to have our versions of memcpy, memcmp, memmove that we own and can make constexpr.?? These are such important concepts.

Also, part 2 brings in constexpr swap. Maybe this is the may to implement an actual memmove?


I don't think this will work in a constant expression:

?? /// Assign @p __new_val to @p __obj and return its previous value.
?? template <typename _Tp, typename _Up = _Tp>
+?????? _GLIBCXX20_CONSTEXPR
?????? inline _Tp
?????? exchange(_Tp& __obj, _Up&& __new_val)
?????? { return std::__exchange(__obj, std::forward<_Up>(__new_val)); }

Because std::__exchange hasn't been marked constexpr. The test passes
because it doesn't call it in a context that requires constant
evaluation:

??const auto x = std::exchange(e, pi);
Derp.

I see the same problem in other tests too:

+?? constexpr std::array<int, 12> car{{0, 1, 2, 3, 4, 5, 6, 6, 8, 9, 9, 11}};
+
+?? const auto out0x = std::adjacent_find(car.begin(), car.end());
+
+?? const auto out1x = std::adjacent_find(car.begin(), car.end(),
+?????????????????????????????????????? std::equal_to<int>())

I will go through all the tests and make sure that some nontrivial calculation is done that contributes to a final bool return.?? And clean up the mess.?? I did this in chunk 2 but I guess I left a lot of chunk 1.

Come to think of it, we could build *insane* concepts after this.?? For good or ill.

Ed

Reply via email to