C++20 Concept结合CRTP代码Clang编译报错是否符合C++标准规范?
问题1:该行为是否符合C++标准预期
这个行为符合当前C++标准的规则设定,核心原因是类模板实例化时机和约束检查时机的差异:
- 当
K继承S<K>时,编译器会首先实例化基类S<K>,此时K的类定义尚未完成,属于不完整类型,编译器还看不到K后续定义的frobulate成员。 - 成员函数的requires约束检查会在所属类模板实例化时触发,此时对
Frobulates<K>的检查自然会失败。而不加requires约束时,成员函数体内的代码会推迟到函数被调用时才实例化,此时K已经是完整类型,就能正常识别frobulate成员。
问题2:讨论该问题的渠道
- 如果是反馈编译器报错信息误导的问题,可以直接向对应编译器的开发团队提交issue,比如Clang的问题可以提交到LLVM官方问题跟踪系统,GCC的问题可以提交到GCC Bugzilla。
- 如果是希望讨论标准规则的合理性、推动规则修改,可以先在C标准公共讨论社区整理共识,再向ISO C标准委员会的官方讨论邮件列表提交议题,符合要求的议题可以进入正式的标准修改流程。
问题3:可行的规避方案
最简单的方案是将带约束的成员函数改为模板函数,通过默认模板参数延迟约束检查时机:
template <typename Derived> struct S { // 把成员函数改成模板,用默认模板参数绑定Derived template<typename D = Derived> int sidefumble() requires Frobulates<D> { D::frobulate(); } };
修改后sidefumble的约束检查会推迟到函数被调用时才执行,此时K已经是完整类型,Frobulates<K>检查就能正常通过,同时保留了concept的约束能力。
如果不需要依赖concept做重载决议,也可以把约束放到函数体内用static_assert实现,也能达到类似效果。
内容的提问来源于stack exchange,提问作者trbabb
相关产品推荐
相关产品推荐

