为什么 Clang 更喜欢主模板而不是 C++17 的专业化?

公民

以下程序是从这个问题中的代码减少的

template <typename T, void (*)(T), typename = void>  
struct S;

template <typename T, void (*f)(T)>
struct S<T, f, void> {};

S<int const, nullptr> s;

在 GCC 的所有版本中,在所有语言版本中,实例化Ss都会选择的特化。

在所有版本的 Clang 中,但仅从 C++17 开始,在实例化s.

我认为值得注意的一些要点是,如果实例化结束<int, nullptr>则永远不会选择主要参数,即不再是第一个参数int const此外,如果第二个参数中的函数指针的签名不包含T作为参数,即如果第二个参数是T (*)()、 或void (*)()则永远不会选择主参数

如果此代码不是 IFNDR,那么哪个编译器是正确的?C++17 语言修订版中是否有一些重大变化?

技术委员会

这是因为 C++17 允许从非类型参数的类型推导出模板类型参数。[temp.deduct.type]/13 :

P从表达式中推导出带有依赖类型声明的非类型模板形参对应的实参的值时,类型中的模板形参P从该值的类型中推导出来的。

因此,当我们尝试匹配S<int const, nullptr>偏特化时,我们T从两个来源推导出偏特化的模板参数

  • 从第一个模板参数int const,我们推导出T=int const
  • 从第二个模板参数(它具有类型,void (*)(int)因为函数参数的顶级 cv 限定被调整掉了),我们推导出T= int

由于我们推导了相互矛盾的结果,推导失败,部分特化不匹配。

类似的例子早在 2019 年就出现在核心反射器上。 有一些共识认为这是标准中的一个缺陷,并且从非类型模板参数的类型推导应该只发生在其他不可推导的事情上。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章