47

Let's say I have an array of integers defined like that:

static constexpr int IntArray[] = {1, 5, 10, 12, 17};

Is there a way to get the minimum or maximum value at compile time?

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
lucaboni
  • 2,334
  • 2
  • 29
  • 41

1 Answers1

67

Let's get the C++17 solution out of the way for future search-landers:

constexpr int IntArray[] = {1, 5, 10, 12, 17};
constexpr int min = *std::min_element(std::begin(IntArray), std::end(IntArray));
static_assert(min == 1);

C++11 is more picky with constexpr functions, so we have to roll out a recursive algorithm. This one is a simple, linear one:

template <class T>
constexpr T &constexpr_min(T &a, T &b) {
    return a > b ? b : a;
}

template <class T>
constexpr T &arrayMin_impl(T *begin, T *end) {
    return begin + 1 == end
        ? *begin
        : constexpr_min(*begin, arrayMin_impl(begin + 1, end));
}

template <class T, std::size_t N>
constexpr T &arrayMin(T(&arr)[N]) {
    return arrayMin_impl(arr, arr + N);
}

constexpr int IntArray[] = {1, 5, 10, 12, 17};
constexpr int min = arrayMin(IntArray);

See it live on Coliru

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
Quentin
  • 62,093
  • 7
  • 131
  • 191
  • Here I am manually trying to implement a c++17 version and there i already one. :( But good to know. ;) – Hayt Oct 27 '16 at 13:35
  • Great answer! Can you make a brief comment of why you use references as return types? It won't work otherwise due to conflicting type deduction (the CV is stripped from non-refs). – vsoftco Oct 27 '16 at 13:50
  • @vsoftco no particular reason, it is just more flexible. I don't encounter any error by removing them, could you show an example ? – Quentin Oct 27 '16 at 13:53
  • @Quentin [Here](http://coliru.stacked-crooked.com/a/a5c3eb6646b5a03a). It suffices to remove the refs return types from `constexpr_min()` and `arrayMin_impl()`. – vsoftco Oct 27 '16 at 13:54
  • @vsoftco ah, I see. You can work around this by calling `constexpr_min` from within `arrayMin_impl`: deduction is skipped, and the types aren't stripped. I had also removed the references from `constexpr_min`'s parameters when testing. – Quentin Oct 27 '16 at 13:58
  • @Quentin Yes indeed. I bumped into this while trying to write my own answer and getting those nasty type deduction errors and meanwhile you wrote yours :) – vsoftco Oct 27 '16 at 13:59
  • 2
    This doesn't technically answer OPs question because you used a `constexpr` and not a `static const` – AndyG Oct 27 '16 at 14:13
  • 20
    @AndyG I assumed that it is an oversight. A `const` array's contents are not compile-time constants, so if it isn't actually `constexpr`, nothing can be done at compile-time at all. – Quentin Oct 27 '16 at 14:16
  • 3
    @Quentin: I wouldn't assume anything haha :-) I think the real answer is your second statement "Nothing can be done at compile-time at all" – AndyG Oct 27 '16 at 14:50
  • @AndyG I added a disclaimer :p – Quentin Oct 27 '16 at 15:38
  • 3
    @AndyG ...and would you then recommend *not* including the info about the `constexpr` case, which is actually useful? – Kyle Strand Oct 27 '16 at 21:35