constexpr int foo()
{
int i[] = {1, 2, 3, 4};
i[0]= i[1]; // OK
return i[0];
}
constexpr int bar()
{
auto tup = std::make_tuple(1, 2, 3, 4);
std::get<0>(tup) = std::get<1>(tup); // OK because T& std::get<I>(tuple) is constexpr !
return std::get<0>(tup);
}
constexpr int baz()
{
std::array<int, 4> i = {1, 2, 3, 4};
i[0]= i[1]; // error reference operator[] is not constexpr
return i[0];
}
int main()
{
constexpr int i1 = foo();
constexpr int i2 = bar();
//constepxr int i3 = baz(); // don't compile
}
// don't compile
template <int... i>
std::array<int, sizeof...(i)> compile_time_sort()
{
constepxr int N = sizeof...(i);
std::array<int, N> a= {i...};
for(int i = 0; i < N ; i++){
// plan was to sort the array here, with classic imperative style
// but it's impossible because a[i] = something don't compile...
}
return a;
}
constepxr std::array<int, 4> sorted_indices = compile_time_sort<4, 6, 1, 9>(); // don't compile
template<int... x, int... idx>
constexpr auto compile_time_sort_imp(std::integer_sequence<int, x...>,
std::integer_sequence<int, idx...>)
{
constexpr int N = sizeof...(x);
int a[] = {x...};
for (int i = 0; i < N - 1; i++)
{
// sort the array, with classic imperative style
//...
}
return std::array<int, N>{a[idx]...}; // and copy the result in a std::array
}
template<int... x>
constexpr auto compile_time_sort_()
{
auto seq = std::integer_sequence<int, x...>();
auto idx = std::make_integer_sequence<int, sizeof...(x)>();
return compile_time_sort_imp(seq, idx);
}
constepxr std::array<int, 4> sorted_indices = compile_time_sort<4, 6, 1, 9>(); // OK !
On 10/13/13 4:55 PM, Gabriel Dos Reis wrote:I wasn't aware of the history, so thanks!
David Krauss <pot...@gmail.com> writes:
[...]
| TBH I don't really understand why we need the constexpr qualifier for
| functions in the first place.
I am not sure what you mean by this: (1) that you are unaware of how the
constexpr keyword came to be? or (2) that you know the history but you
just refuse to understand it?
But why are we stuck with the keyword? For object declarations I think it makes perfect sense, even if a similar argument could be applied that the compiler already knows a constant when it sees one. For functions, though, it deceptively fails to fulfill its apparent (to the uninformed) guarantee.
Actually, it's worse than you think. I originally used N3690 as a C++14 reference for my proposal (a future N3794), then I discovered there's a later draft: N3691. That draft stripped "constexpr" off of all of array's methods, except for size, empty, and max_size. So my proposal followed the later draft.
I could re-add "constexpr" to various array methods during a revision. But you have to show that said decorator is the best choice. Using the "constexpr" decorator forces all implementors to use it for a given method from that point on. So you have to show that a given method can be implemented as constexpr, that all implementors can do it, and that any alternative would be stupid to do.Daryle W.
On Saturday, October 12, 2013 10:43:09 AM UTC-4, thomas....@gmail.com wrote:Hello,
I'm playing around with the relaxed constraints on constexpr functions with clang + libc++ trunk and noticed something strange with std::array : Because std::array lacks a constexpr "reference operator[]" (23.3.2.1.3), it is impossible to instantiate an std::array in a constepxr function and write in it. So it looks a bit inconsistent because we can instantiate and write in a plain C array or std::tuple, but not std::array :
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
On Mon, Oct 14, 2013 at 12:06 AM, Daryle Walker <dar...@gmail.com> wrote:Actually, it's worse than you think. I originally used N3690 as a C++14 reference for my proposal (a future N3794), then I discovered there's a later draft: N3691. That draft stripped "constexpr" off of all of array's methods, except for size, empty, and max_size. So my proposal followed the later draft.N3691 is supposed to be identical to N3690, other than the cover sheet. If it's not, that's unintended, and you should let the project editor know. (N3690 is the Committee Draft, N3691 is the Working Draft). In this instance, I don't see what you're referring to: in both documents, page 764 contains a constexpr operator[], at(), front() and back().
The fact that std::array is applying constexpr to the const overloads
alone is simply a consequence of the fact that the proposing paper was
written at a time, where the rules were different and would not have
allowed that. Fixing the inconsistent difference of constexpr
non-static member functions versus free or static constexpr functions
was very important to get and I think that we really should now
improve the existing standard function specifications.
Hello,
I'm playing around with the relaxed constraints on constexpr functions with clang + libc++ trunk and noticed something strange with std::array : Because std::array lacks a constexpr "reference operator[]" (23.3.2.1.3), it is impossible to instantiate an std::array in a constepxr function and write in it. So it looks a bit inconsistent because we can instantiate and write in a plain C array or std::tuple, but not std::array :
constexpr int foo()
{
int i[] = {1, 2, 3, 4};
i[0]= i[1]; // OK
return i[0];
}
constexpr int bar()
{
auto tup = std::make_tuple(1, 2, 3, 4);
std::get<0>(tup) = std::get<1>(tup); // OK because T& std::get<I>(tuple) is constexpr !
return std::get<0>(tup);
}
constexpr int baz()
{
std::array<int, 4> i = {1, 2, 3, 4};
i[0]= i[1]; // error reference operator[] is not constexpr
return i[0];
}
int main()
{
constexpr int i1 = foo();
constexpr int i2 = bar();
//constepxr int i3 = baz(); // don't compile
}