Clang 不会编译 gcc 会编译的模板专业化
Clang won't compile a template specialization that gcc will
Gcc 可以正常编译,但 Clang(主干)拒绝并显示消息:
<source>:7:8: error: class template partial specialization is not more specialized than the primary template [-Winvalid-partial-specialization]
template<class T, T x>
struct S{};
template<int& x>
struct S<int&, x> { };
这段代码是否正确?
这仅在 -std=c++17
及以后出现。 "more specialized" 的确定需要 synthesizing a pair of function templates from the class templates, synthesizing unique types, values, and templates for the template parameters, and finally performing template argument deduction in both directions。如果推导在一个方向上成功但在另一个方向上不成功,则模板是 "more specialized"。
在这里,Clang 从两个来源推导 T
并得到不同的结果:
- 从明确指定的
int&
,推导出 T := int&
。
- 从非类型参数
x
,它根据通常的推导规则(通常不推导引用类型)推导 T := int
。这种从非类型模板参数的类型推断的能力是在 C++17 中添加的。
这使得推导在两个方向上都失败了,因此偏特化无法通过 "more specialized" 测试。
这看起来像是标准中的缺陷。解决方法是将原始模板中的 T
包装在非推导上下文中。
Gcc 可以正常编译,但 Clang(主干)拒绝并显示消息:
<source>:7:8: error: class template partial specialization is not more specialized than the primary template [-Winvalid-partial-specialization]
template<class T, T x>
struct S{};
template<int& x>
struct S<int&, x> { };
这段代码是否正确?
这仅在 -std=c++17
及以后出现。 "more specialized" 的确定需要 synthesizing a pair of function templates from the class templates, synthesizing unique types, values, and templates for the template parameters, and finally performing template argument deduction in both directions。如果推导在一个方向上成功但在另一个方向上不成功,则模板是 "more specialized"。
在这里,Clang 从两个来源推导 T
并得到不同的结果:
- 从明确指定的
int&
,推导出T := int&
。 - 从非类型参数
x
,它根据通常的推导规则(通常不推导引用类型)推导T := int
。这种从非类型模板参数的类型推断的能力是在 C++17 中添加的。
这使得推导在两个方向上都失败了,因此偏特化无法通过 "more specialized" 测试。
这看起来像是标准中的缺陷。解决方法是将原始模板中的 T
包装在非推导上下文中。