如何在C++中对constexpr函数参数使用static_assert
How to use static_assert for constexpr function arguments in C++?
我的库中有几个简短的constexpr
函数,可以执行一些简单的计算。我在运行时和编译时上下文中都使用它们。
我想在这些函数的主体中执行一些断言,但是assert(...)
在constexpr
函数中无效,static_assert(...)
不能用于检查函数参数。
示例:
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);
}
assert
现在工作了,g++已经实现了N3652,放松了对constexpr函数的约束。此状态页表示这已在gcc5中实现。
assert
(在constexpr函数中)也适用于苹果公司提供的当前clang编译器-std=c++1y
。
目前,我在标准中没有看到任何东西可以保证assert
将在constexpr函数中工作,这样的保证将是对标准的一个受欢迎的补充(至少对我来说是这样)。
更新
Richard Smith提请我注意Daniel Krügler提交的LWG 2234,该文件试图创建我上面提到的保证。这已被纳入C++17中。
抛出异常可能很有用,因为编译器在编译时知道没有抛出异常时会忽略运行时部分。
#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 );
}
实时示例
Daniel Frey的答案的一个改进是在constexpr
函数上使用noexcept
,将运行时错误转换为对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)
希望能有所帮助。
相关文章:
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 收到错误"invalid use of non-static data member 'stu::n' "
- LNK1104:无法打开libpjproject-i386-Win32-vc14-Debug-Static.lib
- 我应该在 C++ 中何时/为什么使用 STATIC?
- 在VS2019项目中集成ImageMagick:x64-windows-static library
- 如何在 assert() 和 static_assert() 之间调度,如果在 constexpr 上下文中依赖?
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- 我关于函数"Assert"的C++代码有问题
- "static char __ = []() -> char"的含义
- 当初始值设定项是基类名时'initializer does not name a non-static data member or base class'错误
- 无法在 DLL 中链接 SDL2-static.lib
- 如何摆脱C++中未解析的外部符号"private: static char"错误?
- assert() 在发布模式下充当标识函数吗?
- 如何编写一个接受如下断言消息的自定义断言函数:assert(false) << "assertio
- C++线程"Call to non-static member function without an object argument"
- 出现这种错误的原因是什么"invalid use of non-static data member "
- static是如何使用ClassA::m_variable处理所有类对象的
- LNK2001:未解析的外部符号public:static类std::vector
- static assert - C++ concepts vs static_assert