【问题标题】:constexpr + multidimension array failsconstexpr + 多维数组失败
【发布时间】:2017-11-05 18:11:21
【问题描述】:

在 C++ 内置多维数组的上下文中,我很难理解 constexpr。下面的例子说明了我的问题。

a) 只要我不将它分配给任何东西,在编译时查看一个值就可以正常工作。

b) 但是如果我尝试将它分配给另一个 constexpr 变量,则会出现编译时错误。

我环顾四周,甚至检查了标准文档。任何能向我解释这一点的人都是真正的大师。 FWIW,我在启用 C++14 的 Xcode 下使用 CLang 8.1 编译它。

using uint8_t = unsigned char;


#if 1
enum class safe_numerics_error : uint8_t {
    success = 0,
    failure,    // result is above representational maximum
    error_count
};
#else
// avoiding enum class fails to solve problem
struct safe_numerics_error {
    const uint8_t m_t;
    constexpr const static uint8_t success = 0;
    constexpr const static uint8_t failure = 1;
    constexpr safe_numerics_error(uint8_t t) :
        m_t(t)
    {}
    constexpr operator uint8_t () const {
        return m_t;
    }
};
#endif

template<typename R>
struct checked_result {
    const safe_numerics_error m_e;
    const union {
        const R m_r;
        char const * const m_msg;
    };
    constexpr /*explicit*/ checked_result(const R & r) :
        m_e(safe_numerics_error::success),
        m_r(r)
    {}
    constexpr /*explicit*/ checked_result(const safe_numerics_error & e) :
        m_e(e),
        m_msg("")
    {}
};

// integers addition
template<class T>
constexpr inline checked_result<T> operator+(
    const checked_result<T> & t,
    const checked_result<T> & u
){
    // "Constexpr variable 'e' must be initialized by a constant expression"
    constexpr const safe_numerics_error x[2][2]{
        // t == success
        {
            // u == ...
            safe_numerics_error::success,
            safe_numerics_error::failure
        },
        // t == positive_overflow_error,
        {
            // u == ...
            safe_numerics_error::failure,
            safe_numerics_error::failure
        }
    };

#if 1  // compile fails
    constexpr const safe_numerics_error e = x
        [static_cast<uint8_t>(t.m_e)]
        [static_cast<uint8_t>(u.m_e)]
    ;

    return
        (safe_numerics_error::success == e)
        ? t.m_r + u.m_r
        : checked_result<T>(e)
    ;
#else  // works as expected
    return
        safe_numerics_error::success == x
            [static_cast<uint8_t>(t.m_e)]
            [static_cast<uint8_t>(u.m_e)]
        ? t.m_r + u.m_r
        : checked_result<T>(x
            [static_cast<uint8_t>(t.m_e)]
            [static_cast<uint8_t>(u.m_e)]
        )
    ;
#endif
}

int main(){
    constexpr const checked_result<unsigned> i = 0;
    constexpr const checked_result<unsigned> j = 0;

    constexpr const checked_result<unsigned> k = i + j;

    // return k.m_r;

    constexpr const checked_result<unsigned> i2 = safe_numerics_error::failure;
    constexpr const checked_result<unsigned> j2 = 0;

    constexpr const checked_result<unsigned> k2 = i2 + j2;
    return k2.m_r;
}

【问题讨论】:

  • 错误是什么?在哪一行?
  • 您的编译器看不到的代码(在#else 块中)只是噪音还是问题的一部分?
  • 对此有两个 cmets:1)在错误情况下,您在 main 末尾返回 m_r,这是无效的,因为该对象是用错误构造的 2)为什么不只是 & 枚举值而不是使用二维数组?即成功 & 成功 == 成功,但失败 & 任何东西 = 失败
  • 哦,另一个:constexpr 变量本质上是 const,所以你不必重新指定。

标签: c++ arrays c++14 constexpr


【解决方案1】:

问题是你不能初始化一个constexpr变量

constexpr const safe_numerics_error e = x
    [static_cast<uint8_t>(t.m_e)]
    [static_cast<uint8_t>(u.m_e)]

其值取决于函数(或方法)的参数(如tu)。

我知道您的 operator+() 是一个 constexpr 并且在您的示例中您仅使用它来初始化 constexpr 值。

但是constexpr 函数/方法可以在编译时运行时使用。所以编译器不能接受不能在运行时执行的constexpr 函数/方法中的代码。

【讨论】:

  • 这个答案总结了它,但要澄清:无论如何,e 都被声明为 constexpr,但如果函数不是用 constexpr 参数调用的,那么该变量不能是 constexpr。如果您只声明 e const,它仍应在编译时使用 constexpr 参数进行评估,但不会出错。
  • @budjmt - 不确定理解您的意思,但如果您声明 e const (如问题中所示),可以使用非 cont 值调用该函数;所以编译器不能接受用于初始化constexpr 变量(无论如何:我看不到在constexpr 函数中声明constexpr 变量(取决于输入参数)的用处:如果函数在编译时执行,如果没有声明constexpr,变量也会在编译时初始化。
  • 没错,它应该只是 const safe_numerics_error e = ...; 我只是说它应该是 const,而不是 constexpr const。 e 本质上不是 constexpr,它只是编译时的 constexpr。
  • 这是正确答案。也就是说,需要删除“constexpr”术语才能使其工作 - 即使它只是在编译计时器时使用 constexpr 参数调用。干得好,这让我明白了。
猜你喜欢
  • 2012-07-22
  • 1970-01-01
  • 2020-09-25
  • 2017-06-27
  • 2012-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多