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

2021-11-13 17:39:02 +08:00
 sl0000
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

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

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

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

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

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

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

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



我们吸艹真的太牛逼辣🥵

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/815172

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX