
struct is { template<typename T> static constexpr bool _vector() { if constexpr (std::is_fundamental_v<T>) { return false; } else { return std::is_same_v<T, std::vector<typename T::value_type>>; } } template<typename T> static constexpr bool vector = _vector<T>(); template<typename T> static constexpr bool vector2 = std::is_fundamental_v<T> || (!std::is_fundamental_v<T> && std::is_same_v<T, std::vector<typename T::value_type>>); }; int main(int argc, const char * argv[]) { std::cout << is::vector2<std::vector<std::vector<int>>::value_type::value_type> << std::endl; return 0; } 使用 vector 是 ok 的
使用 vector2 编译会报 Type 'int' cannot be used prior to '::' because it has no members
template<typename T> static inline constexpr bool A() { ... } template<typename T> static inline constexpr bool B() { ... } template<typename T> bool b1 = if constexpr (A) { return true; } else { return B; } template<typename T> bool b2 = A || (!A && B) 简化一下之前问题
b1中,A成立时不会执行B
b2中,A成立也会执行B
没有constexepr 条件运算符
1 q2577 2021-11-13 17:50:40 +08:00 ``` template<class T> struct is_vector { static constexpr bool value = false; }; template<class T> struct is_vector<std::vector<T> > { static constexpr bool value = true; }; ```` |
4 L4Linux 2021-11-13 18:07:10 +08:00 vector2 逻辑操作左右两边在编译时都会求值,所以出现了 int::value_type 。 |
5 GeruzoniAnsasu 2021-11-13 22:08:42 +08:00 @L4Linux 不能叫「左右两边都求值」吧,我觉得应该叫「模板替换不受表达式本身的逻辑影响」,就,这个表达式本身的逻辑成不成立并不影响用 int 去替换 T ,这个过程也并没有触发 SFINAE ,所以替换失败,编译报错 @sl0000 那么如果用 SFINAE 来容纳替换错误的表达式,就可以工作了: https://gcc.godbolt.org/z/eE5Gar4z3 |
6 edimetia3d 2021-11-13 23:47:50 +08:00 虽然很不想回, 但是既然都看了. 还是回复一下吧. 1. 麻烦问问题前把代码清理一下, 整理一个最简单的 case 出来. 2. @L4Linux 正解 3. 你把 `if constexpr` 换成 `if`也会编译出错, 一样的道理, 至于这个道理你懂不懂, 就看你了. |
7 test0x01 2021-11-14 00:02:32 +08:00 via Android 我发现,十五年没用 c++, 基本上看不懂了 |
8 Caturra 2021-11-14 00:23:56 +08:00 泛型编程中这种伪短路运算是不管用的,实例化出来编译器看不懂就是不行( int::value_type ), 但是传统上可以用 SFINAE 或者简单点直接上特化来解决问题 相比之下 if-constexpr 可读性也挺好,不用写一堆 struct (我也想多用点 17 的特性唉 |
9 GeruzoniAnsasu 2021-11-14 00:56:40 +08:00 |
10 GeruzoniAnsasu 2021-11-14 01:35:31 +08:00 另外这个 constexpr if 填补了我一个知识空白: constexpr 也有类似两段名字查找的特性,如果定义在模板中,那么否定分支中的代码会直接丢弃;如果处于模板实例化阶段,则会正常替换分支两侧的所有需要实例化的模板代码 https://stackoverflow.com/questions/50051473/if-constexpr-in-c17-does-not-work-in-a-non-templated-function 我们吸艹真的太牛逼辣 |