如果在 constexpr 上下文中,如何在 assert() 和 static_assert()、dependend 之间分派?

Bor*_*rph 9 c++ assert static-assert constexpr c++11

在 C++11 constexpr 函数中,assert()不可能使用第二个语句,例如 an 。Astatic_assert()很好,但如果该函数被称为“正常”函数,则它不起作用。逗号运算符可以来帮助wrto。的assert(),而是丑陋和一些工具吐出它的警告。

考虑这样的“getter”,它在断言旁边是完全可构造的。但是我想为运行时和编译时保留某种断言,但不能仅根据“constexpr”上下文进行重载。

template<int Size>
struct Array {
  int m_vals[Size];
  constexpr const int& getElement( int idx ) const
  {
    ASSERT( idx < Size ); // a no-go for constexpr funcs in c++11
    // not possible, even in constexpr calls as being pointed out, but what I would like:
    static_assert( idx < Size, "out-of-bounds" );
    return m_vals[idx];
  }
};
Run Code Online (Sandbox Code Playgroud)

附带条件:C++11,无堆,无异常,无编译器细节。

注意正如评论者指出的那样(谢谢!),static_assert论点是不可能的(但会很好)。在这种情况下,编译器在越界访问时给了我一个不同的错误。

wal*_*nut 3

就像是

void assert_impl() { assert(false); } // Replace body with own implementation

#ifdef NDEBUG // Replace with own conditional
#define my_assert(condition) ((void)0)
#else
#define my_assert(condition) ((condition) ? (void()) : (assert_impl(), void()))
#endif

template<int Size>
struct Array {
  int m_vals[Size];
  constexpr const int& getElement( int idx ) const
  {
    return my_assert(idx < Size), m_vals[idx];
  }
};
Run Code Online (Sandbox Code Playgroud)

如果在需要常量表达式的上下文中使用,它将在断言失败时给出编译时错误(因为它将调用非constexpr函数)。

否则,它将在运行时因调用assert(或您的类似物)而失败。

据我所知,这是你能做的最好的事情。无法使用 的值在需要idx常量表达式的上下文之外强制在编译时进行检查。

逗号运算符语法不太好,但 C++11constexpr功能非常有限。

当然,正如您已经指出的那样,如果在需要常量表达式的上下文中使用该函数,无论如何都会诊断出未定义的行为。

如果您知道assert(或您的类似物)在条件计算结果为 时不会扩展为常量表达式中禁止的任何内容,但如果计算结果为 则扩展为常量表达式中禁止的任何内容truefalse那么您可以直接使用它my_assert,而不是跳过我构建的间接寻址在我的代码中。