C++ C++;2014年1月:constexpr函数中的错误处理?

C++ C++;2014年1月:constexpr函数中的错误处理?,c++,c++14,C++,C++14,假设我想编写一个执行整数平方根的C++1y/14 constexpr函数: constexpr int constexpr_isqrt(int x); 我要执行健全性检查,以确保x为非阴性: constexpr int constexpr_isqrt(int x) { if (x < 0) ??? ... } constexpr int constexpr\u isqrt(int x) { if(x

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

constexpr int constexpr_isqrt(int x);
我要执行健全性检查,以确保
x
为非阴性:

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

    ...
}
constexpr int constexpr\u isqrt(int x)
{
if(x<0)
???
...
}
我应该在上面的
中写什么


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

幸运的是,有一种方法!甚至在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;
}
或者你只是写

constexpr foo(int a)
{
    if ( a < 0 )
    {
        throw std::invalid_argument("Negative!");
    }
    ++a;
    //something else
    return a;
}
constexpr foo(int a)
{
if(a<0)
{
抛出std::无效的_参数(“否定!”);
}
++a;
//别的
返回a;
}

@MarkGarcia的可能重复:我知道条件表达式解决方案,但它不适用于我的问题。特别是上面的
包含多个语句,因此不能表示为单个表达式。我还没有彻底阅读新的常量表达式松弛,但是为什么对
抛出
内部
constepr
函数的限制行为与C++11有所不同@戴普:哇,太酷了。看起来我可以用抛出表达式替换
,这就是我问题的答案。我认为抛出表达式只允许在未计算的上下文中使用。@AndrewTomazos嗯,有点:抛出表达式不能在常量表达式中计算。因此,它是未评估的,但这并不是因为上下文本身是一个未计算的上下文。我认为如果在我的OP中用抛出表达式替换
,它不起作用。您描述的技术只有在函数的其余部分可以表示为表达式时才起作用。@andreTomazos它总是可以的:只需将用于正输入的内容放在单独的表达式中即可函数。@AndrewTomazos请参阅我对C++1y constexpr函数应用此模式的更新答案。您不需要在C++1y版本中引入新函数;如果
,您可以直接使用
。这种模式可以解决C++1y没有的语言缺陷。
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;
}