如果函数被称为constexpr,则有条件static_assert

时间:2019-04-12 08:30:03

标签: c++ constexpr static-assert

我知道有一个针对constexpr()运算符的提议,但这尚未在gcc / clang中实现。我也知道使用一些技巧来实现,例如机器代码编辑:

http://saadahmad.ca/detecting-evaluation-context-inside-constexpr-functions/

我想知道对此是否有某种限制的解决方案:

struct F {
    constexpr F(int v) {
         if constexpr(constexpr()) {
             static_assert(v > 0);
         }
         else {
             assert(v > 0);
         }
    }
};

// ...

constexpr F f{0}; // should trigger a compile-time error

我知道无法以这种方式使用static_assert,但这只是为了澄清问题。

2 个答案:

答案 0 :(得分:3)

在您的特定情况下,您可以只保留断言-由于断言处理程序为非constexpr,因此在条件错误时将阻止编译:

#include <cassert>

struct F {
    constexpr F(int v) {
         assert(v >0);
    }
};

// ...

constexpr F f1{0}; // doesn't compile in debug
constexpr F f2{1}; // compiles

但是,这不会触发发行版中的编译时错误。可以通过创建自己的断言并将调用添加到某些非constepxr函数来解决:

#include <cassert>

// some non-constexpr function
void AssertConditionFailed()
{
}

#define ASSERT_WIH_COMPILE_TIME_CHECK(...) \
    assert(__VA_ARGS__); \
    if (!(__VA_ARGS__)) \
    { \
        AssertConditionFailed(); \
    }\

struct F {
    constexpr F(int v) {
         ASSERT_WIH_COMPILE_TIME_CHECK(v >0);
    }
};

// ...

constexpr F f1{0}; // doesn't compile
constexpr F f2{1}; // compiles

答案 1 :(得分:2)

并非以这种直接方式,因为static_assert根本就不允许在这里使用,并且类似地尝试将v用作模板参数也会失败,因此不会使用enable_if类型的解决方案

出于错误的目的,如果constexpr导致异常,则会出现编译错误。

您可以使用诸如assert(自C ++ 14起允许使用)之类的宏,从而允许在发行版本中对其进行优化,并保持原始调试运行时的行为。

constexpr int foo(int v)
{
    if (v < 0) throw std::invalid_argument("invalid v");
    return v * 2;
}

int main() {
    int a = -1;
    int a2 = foo(a); // Not evaluated at compile time
    constexpr int b = foo(2);
    constexpr int c = foo(-1); // ERROR
}