想必大家都听说过「 Java 程序员的吐槽」说低水平的同事写出这种代码:
```java
if(status == A) {
playwith(A);
}
if(status == B) {
playwith(B);
}
//...
```
然后这种吐槽的下面还会有不少人煞有介事地分析,说可能是老代码删改留下的痕迹,以前没有一个统一的 `playwith()` 函数云云……
今天很高兴地通知大家,我们 c++,即使是 **新代码,也完全可能** 会写出这种段落,而且这种段落完全 **有意义!** :)
Make sense 的关键在于, `playwith()`函数 **不再一定能** 在当前的函数上下文调用了。
c++20 引入的 `consteval function` 会阻止传入任何非 `constexpr` 的参数,所以你在一个运行时的 switch context 里是不能用运行期值去调用 `consteval` 函数的:
```cpp
// 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);
};
```
```cpp
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()` 怎么写呢?
—— 没错,只能判断每个可能的编译期值了,于是我们得到了
```cpp
switch(c){case 1: consteval_fn(1);}
```
> [**在 compiler explorer 上查看这个例子**]( https://gcc.godbolt.org/z/6M6T3E1Y8)
> [例子 on gist]( https://gist.github.com/pnck/eee96898f0d2e332fad5c9b1b0c0676e)
p.s. consteval 函数编译起来是真的很慢,为了这样一个 **编译期 map** 代价还挺大的 |
|