如何在assert()和static_assert()之间分配,如果在constexpr上下文中依赖,则依赖?

问题描述 投票:2回答:2

在C ++ 11 constexpr函数中,无法使用第二条语句,例如assert()static_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
    static_assert( idx < Size, "out-of-bounds" ); // a no-go for non-constexpr calls
    return m_vals[idx];
  }
};

附带条件:C ++ 11,没有堆,没有异常,没有编译器详细信息。

c++ c++11 assert constexpr static-assert
2个回答
0
投票

类似

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

#ifdef NDEBUG // Replace with own conditional
#define my_assert(condition) (void())
#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];
  }
};

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

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

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

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

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

[如果您知道assert(或您的类似物)不会扩展为常量表达式所禁止的任何内容,那么您可以直接使用它代替my_assert


0
投票

static_assert不能在这里使用。常量表达式中不允许constexpr函数的参数。因此,在给定的约束下,您的问题没有解决方案

但是,我们可以通过两个约束来解决问题

  1. 不使用static_assert(使用其他方法来产生编译时诊断),以及

  2. 忽略逗号运算符“很丑陋,并且某些工具会吐出警告。” (由于C ++ 11 constexpr函数的严格要求,显示其丑陋是不幸的结果)

  3. 然后,我们可以使用普通的assert

template <int Size>
struct Array {
  int m_vals[Size];
  constexpr const int& getElement(int idx) const
  {
    return assert(idx < Size), m_vals[idx];
  }
};

在恒定评估上下文中,这将产生编译器错误,例如error: call to non-'constexpr' function 'void __assert_fail(const char*, const char*, unsigned int, const char*)'

© www.soinside.com 2019 - 2024. All rights reserved.