我的库中有几个简短的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);
}
答案 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 );
}
答案 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 functions,assert
将对你有用。目前,this status page表示尚未实施。
assert
在Apple提供的当前clang编译器上使用-std=c++1y
工作(在constexpr函数中)。
目前,我没有在标准中看到任何保证assert
将在constexpr函数中起作用的标准,并且这样的保证将成为标准的一个受欢迎的补充(至少是我)。
<强>更新强>
理查德史密斯提醒我注意丹尼尔克鲁格勒提交的LWG 2234,他试图创造我上面提到的保证。