[PATCH 1/3] C++20 constexpr lib part 1/3

Jonathan Wakely jwakely@redhat.com
Thu Jun 27 23:31:00 GMT 2019


On 27/06/19 19:07 -0400, Ed Smith-Rowland wrote:
>On 6/27/19 1:06 PM, Ville Voutilainen wrote:
>>On Thu, 27 Jun 2019 at 19:55, Ed Smith-Rowland via libstdc++
>><libstdc++@gcc.gnu.org> wrote:
>>>>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.
>>As was the case with the iterator patch, it's not a question of doing
>>a nontrivial calculation, but
>>a question of initializing a constexpr variable with the result. (Yeah
>>sure a non-type template
>>argument would also work but eurgh). Then, and only then, have we
>>proven that the code
>>works in a constexpr context. Initializing a const doesn't do that.
>>constinit would, but that's
>>C++20.
>>
>Ok, why isn't
>
>?? static_assert(test());
>
>a constexpr context?

It is, I missed that the array test does that at the bottom of the
file.


>The std::exchange test passed originally because, unlike all the other 
>algo tests I had neglected to call the test function in a constexpr 
>context.
>
>Note that constexpr_iter.c is this:
>
>----
>
>constexpr int
>test()
>{
>?? constexpr std::array<int, 3> a1{{1, 2, 3}};
>?? static_assert(1 == *a1.begin());
>?? auto n = a1[0] * a1[1]* a1[2];
>?? static_assert(1 == *a1.cbegin());
>
>?? std::array<int, 3> a2{{0, 0, 0}};
>?? auto a1i = a1.begin();
>?? auto a1e = a1.end();
>?? auto a2i = a2.begin();
>?? while (a1i != a1e)
>?????? *a2i++ = *a1i++;
>
>?? return n;
>}
>
>void
>run_test()
>{
>?? constexpr int n = test();
>}
>
>----
>
>Things inside the function can, and in many cases for this capability 
>must, be mutable.?? As long as the input and the final output is a 
>literal we should be good, no?
>
>Also when I assign returned iterators to constexpr I get:
>
>/home/ed/gcc_git/libstdc++-v3/testsuite/25_algorithms/find_if_not/constexpr.cc:36: 
>error: '(((std::array<int, 12>::const_pointer)(& ca0.std::array<int, 
>12>::_M_elems)) + 28)' is not a constant expression.

Yes, I tried adding that and got the same error, which is why I
thought the test had the same problem as the std::exchange one.

I'm not sure what causes that error, I'll take a look tomorrow.




More information about the Libstdc++ mailing list