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 · 2025 次点击
    这是一个创建于 1106 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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   ·   实用小工具   ·   1017 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:38 · PVG 03:38 · LAX 11:38 · JFK 14:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.