如何在C ++中使用static_assert用于constexpr函数参数?

时间:2014-09-27 08:14:32

标签: c++ c++11 assert constexpr

我的库中有几个简短的constexpr函数可以执行一些简单的计算。我在运行时和编译时上下文中都使用它们。

我想在这些函数的主体中执行一些断言,但assert(...)constexpr函数中无效,static_assert(...)不能用于检查函数参数。< / p>

示例:

constexpr int getClamped(int mValue, int mMin, int mMax) noexcept
{
    assert(mMin <= mMax); // does not compile!
    return mValue < mMin ? mMin : (mValue > mMax ? mMax : mValue);
}

有没有办法检查该函数是在运行时还是编译时常量中执行,只有在运行时执行时才执行assert

constexpr int getClamped(int mValue, int mMin, int mMax) noexcept
{
    assert_if_runtime(mMin <= mMax); 
    return mValue < mMin ? mMin : (mValue > mMax ? mMax : mValue);
}

3 个答案:

答案 0 :(得分:8)

抛出异常可能很有用,因为编译器在编译时知道没有抛出异常时会忽略运行时部分。

#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

答案 1 :(得分:6)

对Daniel Frey的回答是对noexcept函数使用constexpr将运行时错误转换为对std::terminate的调用。断言失败是不可恢复的;他们应该立即停止这个过程。将它们变成异常是个坏主意。

#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
}

我的运行时错误如下:

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

希望有所帮助。

答案 2 :(得分:4)

我相信一旦g ++实现N3652, Relaxing constraints on constexpr functionsassert将对你有用。目前,this status page表示尚未实施。

assert在Apple提供的当前clang编译器上使用-std=c++1y工作(在constexpr函数中)。

目前,我没有在标准中看到任何保证assert将在constexpr函数中起作用的标准,并且这样的保证将成为标准的一个受欢迎的补充(至少是我)。

<强>更新

理查德史密斯提醒我注意丹尼尔克鲁格勒提交的LWG 2234,他试图创造我上面提到的保证。