为什么强制constexpr只有编译时错误

Why force constexpr have compile time error only?

本文关键字:编译时错误 constexpr 为什么      更新时间:2023-10-16

我正在观看CppCon 2015: Scott Schurr " constexpr: Applications",在19'28"他展示了一个只强制编译时错误的技巧:

一种强制编译时的方法?

  • 不符合标准
  • 但是一个hack有时是有效的

Throw

extern const char* compile11_bin_invoked_at_runtime;
template <typename T = std::uint32_t>
constexpr T compile11_bin(
  constexpr_txt t,
  std::size_t i = 0, // index
  std::size_t b = 0, // bit count
  T x = 0) // accumulator
{
  return
    i >= t.size() ? x : // end recursion
    b >= std::numeric_limits<T>::digits ?
    throw std::overflow_error("Too many bits!") :
    t[i] == ',' ? compile11_bin<T>(t, i+1, b, x) :
    t[i] == '0' ? compile11_bin<T>(t, i+1, b+1, (x*2)+0) :
    t[i] == '1' ? compile11_bin<T>(t, i+1, b+1, (x*2)+1) :
    throw std::domain_error( // Only '0', '1', and ','
    compile11_bin_invoked_at_runtime);
}

我很好奇,强制constexpr只有编译时错误的动机是什么?

编译时错误总是优于运行时错误。

为什么?因为编译时错误可以在不运行应用程序的情况下修复,因此可以很容易地修复。通过抛出一个未解析的外部符号,您可以强制将compile11_bin的结果存储在constexpr变量中,这使您能够更快地检测错误。

幻灯片中的例子是:

constexpr auto maskA = constexpr11_bin<std::uint8_t>("1110 0000");
auto maskB = constexpr11_bin<std::uint8_t>("0001 1111");

这里,maskA会导致编译时错误,这个错误很容易修复。另一方面,maskB导致运行时错误,因为maskB不是constexpr,所以结果不必在编译时计算,并且您将获得运行时错误。

这是因为compile11_bin_invoked_at_runtime是一个未解析的外部符号,每个符号都必须有一个定义,所以你在编译时得到一个错误,即使它不是编译器本身抱怨。