c++ 模版编译问题, func -> bool { if constexpr A else B } 和直接声明 static constexpr bool 编译的区别 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sl0000
V2EX    C++

c++ 模版编译问题, func -> bool { if constexpr A else B } 和直接声明 static constexpr bool 编译的区别

  •  
  •   sl0000 2021-11-13 17:39:02 +08:00 2691 次点击
    这是一个创建于 1494 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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

    第 1 条附言    2021-11-14 23:05:03 +08:00
    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

    @edimetia3d

    第 2 条附言    2021-11-17 13:12:00 +08:00

    没有constexepr 条件运算符

    第 3 条附言    2021-11-17 13:12:09 +08:00
    没有 constexepr 条件运算符
    10 条回复    2021-11-14 01:35:31 +08:00
    q2577
        1
    q2577  
       2021-11-13 17:50:40 +08:00   1
    ```
    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;
    };
    ````
    sl0000
        2
    sl0000  
    OP
       2021-11-13 17:51:39 +08:00
    @q2577 居然这么简单。。。但是 上面的编译问题 能解释一下吗
    q2577
        3
    q2577  
       2021-11-13 17:56:34 +08:00
    @sl0000 可能是编译器问题?
    L4Linux
        4
    L4Linux  
       2021-11-13 18:07:10 +08:00   2
    vector2 逻辑操作左右两边在编译时都会求值,所以出现了 int::value_type 。
    GeruzoniAnsasu
        5
    GeruzoniAnsasu  
       2021-11-13 22:08:42 +08:00   1
    @L4Linux 不能叫「左右两边都求值」吧,我觉得应该叫「模板替换不受表达式本身的逻辑影响」,就,这个表达式本身的逻辑成不成立并不影响用 int 去替换 T ,这个过程也并没有触发 SFINAE ,所以替换失败,编译报错

    @sl0000 那么如果用 SFINAE 来容纳替换错误的表达式,就可以工作了:

    https://gcc.godbolt.org/z/eE5Gar4z3
    edimetia3d
        6
    edimetia3d  
       2021-11-13 23:47:50 +08:00
    虽然很不想回, 但是既然都看了. 还是回复一下吧.

    1. 麻烦问问题前把代码清理一下, 整理一个最简单的 case 出来.
    2. @L4Linux 正解
    3. 你把 `if constexpr` 换成 `if`也会编译出错, 一样的道理, 至于这个道理你懂不懂, 就看你了.
    test0x01
        7
    test0x01  
       2021-11-14 00:02:32 +08:00 via Android
    我发现,十五年没用 c++, 基本上看不懂了
    Caturra
        8
    Caturra  
       2021-11-14 00:23:56 +08:00
    泛型编程中这种伪短路运算是不管用的,实例化出来编译器看不懂就是不行( int::value_type ),
    但是传统上可以用 SFINAE 或者简单点直接上特化来解决问题

    相比之下 if-constexpr 可读性也挺好,不用写一堆 struct (我也想多用点 17 的特性唉
    GeruzoniAnsasu
        9
    GeruzoniAnsasu  
       2021-11-14 00:56:40 +08:00
    @sl0000

    发现#5 的代码写错了,改正了一点细节,这个例子可以工作

    https://gcc.godbolt.org/z/h3nnch497
    GeruzoniAnsasu
        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



    我们吸艹真的太牛逼辣
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     911 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 21:47 PVG 05:47 LAX 13:47 JFK 16:47
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86