【发布时间】:2021-06-18 19:03:03
【问题描述】:
下面的program是从这个question中的代码缩减而来的:
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 中,在所有语言修订版中,当 s 被实例化时,会选择 S 的特化。
在所有版本的 Clang 中,但仅从 C++17 开始,在实例化 s 时会选择主模板。
我认为值得注意的几点是,如果实例化结束<int, nullptr>,则永远不会选择主参数,即第一个参数不再是int const。此外,如果第二个参数中的函数指针的签名不包含T 作为参数,即如果第二个参数是T (*)() 或void (*)(),则永远不会选择主参数。
如果这段代码不是 IFNDR,哪个编译器是正确的? C++17 语言版本是否有一些重大变化?
【问题讨论】:
-
主模板和专业化之间的区别在于第三个参数......无论如何都是
void。 so clang bug 或 ILNDR IMO。 -
详细分析可能会有所帮助:尝试了insightc++(基于clang)并尝试了更小的场景(删除了默认参数)。 C++17 编译失败,但之前没有:cppinsights.io/s/da6745e4 我没有看到任何格式错误的代码,也没有理解错误消息,即没有真正的专业化。
-
PS:至少我减少的问题与stackoverflow.com/questions/51779059/…有点相关
-
[temp.class.spec.match]/3 (C++14) 在 C++17 ([temp.class.spec.match]) 中作为 P0127R2 的一部分被删除,并指出它是“多余的”;也许 Clang 对此采取了行动。无论哪种方式,如果我推测,这可以说与 P0127R2 及其对令人困惑的部分排序规则的更改有关。
标签: c++ templates language-lawyer template-specialization