GCC与Clang处理私有static constexpr成员访问的标准合规性问询
GCC与Clang对模板中私有成员访问的行为差异
先看这段代码:
class Base { static constexpr int PRIVATE = 1; }; struct Derived : public Base { template <class T> int bar( T & t ) { return PRIVATE; } }; int main() { Derived d; int i = 3; d.bar(i); }
这段代码在GCC里能正常运行,但到Clang下就编译失败了。
我发现两款编译器在处理模板中私有成员访问的逻辑上有明显差异:
- 针对私有成员函数:GCC会在模板函数实例化时才检测非法访问,未实例化的话就不会管;而Clang不管模板有没有实例化,只要代码里出现了私有成员访问就直接报错。
- 但换成私有
static constexpr变量时情况反过来了:GCC哪怕在模板实例化之后,也不会阻止这种私有访问(直到最新的8.1版本都是如此),而Clang会正确识别并报错。
这就引出了一个问题:在这个场景下,到底哪款编译器的行为符合C++标准的要求?
我个人觉得GCC允许访问私有static constexpr变量的行为不太合理,但这个问题在最新版本的GCC里依然存在,看起来像是开发者有意为之的设计。
特别感谢paxdiablo给出的清晰全面解答,根据他的建议我做了更全面的测试,发现GCC的问题根源其实出在static修饰符上。整理的测试对比结果如下:
| 私有成员类型 | GCC | Clang |
|---|---|---|
| static const | 接受 | 拒绝 |
| static constexpr | 接受 | 拒绝 |
| static | 接受 | 拒绝 |
| const | 实例化时拒绝 | 拒绝 |
| 无修饰符 | 实例化时拒绝 | 拒绝 |
| static函数 | 实例化时拒绝 | 拒绝 |
| 普通函数 | 实例化时拒绝 | 拒绝 |
注:"实例化时拒绝"指GCC仅在模板实际被实例化的时候,才会检测并拒绝非法的私有成员访问。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

