10

The following program prints out a shuffled deck of cards (as integers):

#include <array>
#include <algorithm>
#include <random>
#include <iostream>

typedef unsigned int card;
typedef std::array<card, 52> deck;
auto shuffled_deck(){
    deck d = {};
    std::iota(d.begin(), d.end(), 0);
    std::shuffle(d.begin(), d.end(), std::default_random_engine());
    return d;
}

int main(){
    for(auto& i: shuffled_deck()) std::cout << i << ", ";
}

Compiled with g++ -std=c++17 the program runs and prints:

18, 34, 27, 46, 11, 3, 12, 19, 33, 21, 41, 13, 36, 49, 40, 22, 8, 9, 28, 2, 6, 30, 50, 24, 37, 32, 35, 4, 15, 45, 47, 43, 14, 44, 20, 23, 29, 7, 31, 51, 26, 10, 42, 48, 0, 38, 5, 16, 17, 1, 25, 39,

This is great, but intuition tells me that this deck could be created at compile-time, so I make the shuffled_deck method constexpr

constexpr auto shuffled_deck(){
    deck d = {};
    std::iota(d.begin(), d.end(), 0); // Error! Iota isn't constexpr!
    std::shuffle(d.begin(), d.end(), std::default_random_engine());
    return d;
}

Compiling with g++ -std=c++17 gives you compilation error saying that std::iota is not constexpr. My question is why? Surely std::iota is determinable at compile-time. Is the standard library just lagging behind on this feature?

Willy Goat
  • 1,175
  • 2
  • 9
  • 24
  • 7
    If you're convinced that "std::iota is determinable at compile-time ", then out of curiosity, how would *you* implement `iota` to fulfill the requirements of `constexpr` ? I'm particularly curious how `begin()`, and `end()`, neither of which are `constexpr`, are going to make that feasible. – WhozCraig Jan 12 '17 at 02:30
  • In your case - a constant value passed to the template - a solution may be determinable at compile time. But how would a more generic solution be implemented so it would also be determinable this way? – tmpearce Jan 12 '17 at 02:40
  • 9
    @WhozCraig : This is tagged `c++1z`; in C++17, `begin` and `end` _are_ constexpr, and even if they weren't one could use `data` and `size`. None of which is about `iota`, which cares nothing of what iterators you give it... – ildjarn Jan 12 '17 at 03:13
  • 1
    @WhozCraig I never considered `begin()` and `end()` not being `constexpr`. Is there a way to use these algorithms without `begin()` and `end()`? I guess I could replace `iota` with a `for` loop which sets the elements of the array to `i`, but I thought that's what `iota` did. EDIT: ildjarn says `begin()` and `end()` are `constexpr` – Willy Goat Jan 12 '17 at 03:19
  • 3
    @WillyGoat ildjarn hit the nail on the head. My tc runs through 14, not 1z, so naturally they're not constexpr there. If they are in 1z, I see no reason this couldn't be ce in your case. And props to ildjarn for mentioning the tag I missed. Props, dude. – WhozCraig Jan 12 '17 at 03:22
  • 5
    Nobody wrote a proposal in time for C++17 for it to be made `constexpr`. You may want to contact the author of [P0202](https://wg21.link/P0202) to see if he's amenable to adding `` to the list since it goes well thematically with that paper. – T.C. Jan 12 '17 at 05:11
  • Is there any update on this (as we are two years further now)? I cannot find whether or not it is considered for C++17 or C++20. – Michiel uit het Broek Dec 17 '18 at 13:22
  • @MichieluithetBroek No, it is still not constexpr in C++20. – L. F. Aug 27 '19 at 12:21

1 Answers1

1

This should be proposed to be added to the standard. As it stands now it just isn't.

Jubin Chheda
  • 534
  • 4
  • 11
  • 2
    Update: `std::iota` is `constexpr` in C++20, after [P1645R1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1645r1.html) has been accepted. See https://en.cppreference.com/w/cpp/algorithm/iota. The proposal also made [some other functions](https://stackoverflow.com/a/58778742/7120360) in `` `constexpr`. – drel Jun 30 '20 at 21:19