Static_assert by reference pattern argument type

What I'm trying to do is a simple template clamp function. I want to provide upper >= lowerat runtime and at compile time.

template <typename T>
T clamp(const T& lower, const T& upper, const T& n)
{
    weak_assert(upper >= lower);
    return std::max(lower, std::min(n, upper));
}

It seems reasonable to write:

static_assert(upper >= lower, "invalid bounds");

However, when called with no arguments constexpr, the compiler gives me this:

Static_assert expression is not an integral constant expression
In instantiation of function template specialization 'clamp<int>' requested here

Is there any way to achieve this correctly? When called with constexpr(say clamp<int>(0, 10, myvar)static_assert must be running, otherwise would a normal dynamic assert do it?

+4
source share
2 answers

Starting with C ++ 14 is assert()allowed in constexpr functions, but even with C ++ 11 you can fool it using operator ,:

#include <cassert>

template <typename T>
constexpr T clamp(const T& lower, const T& upper, const T& n)
{
    return assert(upper >= lower), std::max(lower, std::min(n, upper));
}
+6

static_assert , ++ constexpr... , , std::integral_constant , . , , :

#include <algorithm>
#include <type_traits>

template <class T, T val>
using ic = std::integral_constant<T, val>;

template <typename T, T lower, T upper>
T clamp(ic<T, lower>, ic<T, upper>, const T& n)
{
    static_assert(upper >= lower, "invalid bounds");
    return std::max(lower, std::min(n, upper));
}

int main() {
    clamp(ic<std::size_t, 5>{},  ic<std::size_t, 10>{}, std::size_t{8});
    // clamp(ic<std::size_t, 10>{},  ic<std::size_t, 5>{}, std::size_t{8}); // static assertion failed: invalid bounds
}

[live demo]

+1

Source: https://habr.com/ru/post/1668094/


All Articles