How to use static_assert for constexpr function arguments in C++?

China☆狼群 提交于 2019-12-01 15:25:52

I believe that assert will work for you once g++ implements N3652, Relaxing constraints on constexpr functions. Currently, this status page indicates that this has not yet been implemented.

assert does work (in constexpr functions) on the current clang compiler shipped by Apple, with -std=c++1y.

At this time, I see nothing in the standard that assures one that assert will work in constexpr functions, and such an assurance would be a welcome addition to the standard (at least by me).

Update

Richard Smith drew my attention to LWG 2234 submitted by Daniel Krügler which is attempting to create the assurance I refer to above.

Throwing an exception might be useful as the compiler will ignore the run-time part when it knows at compile-time that the exception is not thrown.

#include <cassert>

constexpr int getClamped(int mValue, int mMin, int mMax)
{
    return ( mMin <= mMax ) ? 
           ( mValue < mMin ? mMin : (mValue > mMax ? mMax : mValue) ) :
           throw "mMin must be less than or equal to mMax";
}

int main( int argc, char** argv )
{
    // These two work:
    static_assert( getClamped( 42, 0, 100 ) == 42, "CT" );
    assert( getClamped( argc, 0, 100 ) == argc );

    // Fails at compile-time:
    // static_assert( getClamped( 42, 100, 0 ) == 42, "CT" );

    // Fails at run-time:
    // assert( getClamped( argc, 100, 0 ) == argc );
}

Live example

A refinement on Daniel Frey's answer is to use noexcept on the constexpr function to turn the runtime error into a call to std::terminate. Assertion failures are unrecoverable; they should halt the process immediately. Turning them into exceptions is a very bad idea.

#include <exception>
#include <stdexcept>

struct assert_failure
  : std::logic_error
{
    explicit assert_failure(const char *sz)
      : std::logic_error(sz)
    {}
};

constexpr bool in_range(int i, int j, int k) noexcept
{
    return (i <= j && j <= k) ? true : throw assert_failure("input not in range");
}

int main(int argc, char* argv[])
{
    constexpr bool b1 = in_range(0, 4, 5); // OK!
    constexpr bool b2 = in_range(0, 6, 5); // Compile-time error!
    bool b3 = in_range(0, 4, argc);        // May or may not terminate the process
}

The runtime error for me looks like:

terminate called after throwing an instance of 'assert_failure'
  what():  input not in range
Aborted (core dumped)

Hope that helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!