On Thu, 27 Jun 2019 at 19:55, Ed Smith-Rowland via libstdc++ <libstd...@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.