为什么强制 constexpr 只有编译时错误?
Why force constexpr have compile time error only?
我在看CppCon 2015: Scott Schurr “constexpr: Applications", on 19'28"他展示了一个只强制编译时错误的技巧:
A Way to Force Compile-Time Only?
- Not within the standard
- But a hack that sometimes works
Unresolved Symbol In 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
是一个未解析的外部符号,每个符号都必须有一个定义,所以你会在编译时得到一个错误,即使抱怨的不是编译器本身。
我在看CppCon 2015: Scott Schurr “constexpr: Applications", on 19'28"他展示了一个只强制编译时错误的技巧:
A Way to Force Compile-Time Only?
- Not within the standard
- But a hack that sometimes works
Unresolved Symbol In 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
是一个未解析的外部符号,每个符号都必须有一个定义,所以你会在编译时得到一个错误,即使抱怨的不是编译器本身。