想必大家都听说过「 Java 程序员的吐槽」说低水平的同事写出这种代码:
if(status == A) { playwith(A); } if(status == B) { playwith(B); } //... 然后这种吐槽的下面还会有不少人煞有介事地分析,说可能是老代码删改留下的痕迹,以前没有一个统一的 playwith() 函数云云……
今天很高兴地通知大家,我们 c++,即使是 新代码,也完全可能 会写出这种段落,而且这种段落完全 有意义! :)
Make sense 的关键在于, playwith()函数 不再一定能 在当前的函数上下文调用了。 c++20 引入的 consteval function 会阻止传入任何非 constexpr 的参数,所以你在一个运行时的 switch context 里是不能用运行期值去调用 consteval 函数的:
// this lambda is conteval auto flatten = [](E _e) consteval { auto [id, extra] = static_map(_e); auto [name, info] = std::move(extra); return make_tuple(static_cast<int>(_e), id, name, info); }; cout << std::apply( [](auto &&...args) { return std::format("in case {}, id {} (name:{}) has info: {}\n", args...); }, // flatten(FOO)); // work, but only with literal to_runtime(flatten, e)); // work at runtime 那这个 to_runtime() 怎么写呢? 没错,只能判断每个可能的编译期值了,于是我们得到了
switch(c){case 1: consteval_fn(1);} p.s. consteval 函数编译起来是真的很慢,为了这样一个 编译期 map 代价还挺大的
