C++推导指引与尾置返回类型中的依赖名称问题:是GCC的Bug还是代码格式非法?
C++推导指引与尾置返回类型中的依赖名称问题:是GCC的Bug还是代码格式非法?
嘿,这个问题问到点子上了!先给你个明确结论:你的代码完全符合C++23标准要求,GCC拒绝编译它属于编译器实现上的Bug,Clang的行为才是正确的。
先把你的完整代码(补全了截断部分)贴出来方便大家看:
#include <utility> // wraps lvalues by ref and xvalues by move template <typename T, auto size_> struct wrap { T obj; }; // GCC报错,Clang正常通过的推导指引 template <typename T> wrap(T && a) -> wrap<T, size(a)>;
为什么代码是合法的?
C++23正式允许在类模板推导指引中使用尾置返回类型语法,而这里的size(a)属于依赖于模板参数T的表达式——在模板实参推导阶段,编译器会先推导出T的具体类型,再解析a的类型并计算size(a)的值,最后确定wrap的第二个非类型模板参数。
按照C++标准的规则,推导指引的尾置返回类型部分属于模板的“依赖语境”,所有依赖名称会等到模板实参确定后再进行查找和求值,这和普通模板函数的处理逻辑是一致的。只要size在实例化语境中是可见的(比如你实现了对应的size函数,或者使用标准库的std::size并包含了对应头文件),这个表达式就完全合法。
为什么GCC会报错?
GCC在处理推导指引的尾置返回类型中的依赖表达式时,存在实现缺陷——它没有正确处理“先推导模板参数,再解析依赖名称”的流程,错误地在模板定义阶段就尝试解析size(a),而此时T还未被推导,自然会认为这是无效的表达式。
临时 workaround(如果需要兼容GCC)
如果你现在必须让代码在GCC上跑起来,可以换一种写法,不用尾置返回类型的推导指引,改用显式的构造辅助函数:
template <typename T> auto make_wrap(T && a) -> wrap<T, size(a)>;
然后通过auto w = make_wrap(your_obj);来构造wrap对象,绕开GCC对推导指引尾置返回类型的处理bug。
总的来说,你的代码写法是完全合规的,放心提交GCC的Bug报告就好啦。
内容来源于stack exchange
相关产品推荐
相关产品推荐

