Clang中non-type template arguments引用子对象报错原因及方案问询
问题原因
这个编译差异是C++标准版本对非类型模板参数的规则差异和编译器默认标准模式不同导致的,不属于Clang的特性缺失:
- C++17及更早的标准明确规定:指针类型的非类型模板参数,只能指向完整的对象、函数或者空指针,不允许指向类的成员子对象、数组元素这类子对象的地址。你遇到的Clang报错就是严格遵循了这个旧标准的要求。
- GCC在旧标准模式下默认开启了相关扩展,支持子对象指针作为非类型模板参数,所以能编译通过。
- 这个限制在C++20标准中已经被移除,符合要求的子对象指针可以合法作为非类型模板参数使用。
规避方案
除了拷贝对应值存储为独立常量外,还有两种成本更低的解决方案:
- 指定C++20及以上标准编译
不需要修改任何代码,只需要给Clang的编译参数加上-std=c++20(或更高的-std=c++23)即可编译通过,是最推荐的方案。 - 适配C++17及更早标准的修改方案
如果你的项目必须兼容C++17及更早版本,可以调整模板参数传递的指针粒度,改为传递整个父对象的指针,在模板内部访问对应成员即可,示例代码如下:
struct S { int a; }; template <const S* s> struct T { // 内部访问子对象,不需要额外拷贝值 static constexpr const int* a_ptr = &s->a; }; constexpr S kS{.a = 42}; constexpr T<&kS> kT; int main() { return 0; }
内容的提问来源于stack exchange,提问作者dtldarek
相关产品推荐
相关产品推荐

