0

My understanding was that the parameters of consteval functions can't be used in static_asserts because they are not considered constant expressions. However, that only seems to be the case sometimes:

// using gcc 13.1 with -std=c++20

#include <array>
#include <concepts>
#include <iostream>
#include <ranges>

template<std::ranges::input_range T, std::integral U>
consteval int assertStuff2(T ok, U not_ok) {
    // (1) both compile fine
    static_assert(std::ranges::size(ok) != 5);
    static_assert(ok.size() != 5);
    
    // (2) compiler error!
    // "non-constant condition for static assertion:
    //    'not_ok' is not a constant expression"
    static_assert(not_ok != 5);

    return 0;
}

int main() {
    std::cout << assertStuff2(std::array<int, 3>{5, 3, 2}, 2);
}

Why is ok usable in a static_assert but not_ok isn't?

1 Answers1

4

Why is ok usable in a static_assert but not_ok isn't?

ok, like not_ok, is not a constant expression, so you can't do static_assert(ok != std::array<int, 3>{}) either.

However, ok.size() is still usable in static_assert, because ok is not a reference type, and its size() is a constexpr function that returns the template parameter N, which makes the whole expression can be treated as a constant expression ([expr.const]).

ranges::size(t) ultimately returns t.size(), so it is also a constant expression.

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
  • What might be informative is the fact those static asserts also work in mere `constexpr` functions. The `consteval` part didn't permit more `static_assert` usage here. – Yakk - Adam Nevraumont Aug 01 '23 at 13:33