想必大家都听说过「 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 代价还挺大的
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.