c++ 1y/14: constexpr函数中的错误处理

C++1y/14: Error handling in constexpr functions?

本文关键字:错误 处理 函数 constexpr 1y c++      更新时间:2023-10-16

假设我想写一个c++ 1y/14 constexpr函数来执行整数平方根:

constexpr int constexpr_isqrt(int x);

我想执行一个完整性检查以确保x是非负的:

constexpr int constexpr_isqrt(int x)
{
    if (x < 0)
        ???
    ...
}

我应该在上面的???中写什么?

理想情况下,如果函数在常量上下文中求值,应该会导致编译时错误,如果在运行时调用,则会导致运行时错误(例如abort或抛出异常)。

你很幸运,有办法!甚至在c++ 11中!使用例外:

#include <iostream>
#include <stdexcept>
constexpr int foo(int a)
{
    return (a >= 0) ? a : throw std::invalid_argument("Negative!");
}
template <int n>
struct Foo
{
};
int main()
{
    Foo<foo(1)> f1();  // fine, guaranteed compile time
    Foo<foo(-1)> f2(); // bad, compile time error
    foo(1);            // fine, not necessarily at compile time
    try
    {
        foo(-1);       // fine, definitively not at compile time
    }
    catch ( ... )
    {
    }
    return 0;
}

演示:http://ideone.com/EMxe2K

对于不允许的情况,GCC有一个相当好的错误消息:

prog.cpp: In function ‘int main()’:
prog.cpp:17:12:   in constexpr expansion of ‘foo(-1)’
prog.cpp:6:63: error: expression ‘<throw-expression>’ is not a constant-expression
  return (a >= 0) ? a : throw std::invalid_argument("Negative!");

对于c++ 1y constexpr函数,看起来像

constexpr foo(int a)
{
    if ( a < 0 )
    {
        // error!
    }
    ++a;
    //something else
    return a;
}
你可以通过引入一个新函数来使用上面的模式:
constexpr foo_positive(int a)
{
   ++a;
   //something else
   return a;
}
constexpr int foo(int a)
{
   return (a >= 0) ? foo_positive(a) : throw std::invalid_argument("Negative!");
}

或者直接写

constexpr foo(int a)
{
    if ( a < 0 )
    {
        throw std::invalid_argument("Negative!");
    }
    ++a;
    //something else
    return a;
}