cig*_*ien 11 c++ templates template-specialization language-lawyer
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;
Run Code Online (Sandbox Code Playgroud)
在 GCC 的所有版本中,在所有语言版本中,实例化S时s都会选择的特化。
在所有版本的 Clang 中,但仅从 C++17 开始,在实例化s.
我认为值得注意的一些要点是,如果实例化结束<int, nullptr>,则永远不会选择主要参数,即不再是第一个参数int const。此外,如果第二个参数中的函数指针的签名不包含T作为参数,即如果第二个参数是T (*)()、 或void (*)(),则永远不会选择主参数。
如果此代码不是 IFNDR,那么哪个编译器是正确的?C++17 语言修订版中是否有一些重大变化?
这是因为 C++17 允许从非类型参数的类型推导模板类型参数。[温度扣除类型]/13 :
当从表达式推导与使用依赖类型声明的非类型模板参数对应的实参值时
P,类型中的模板参数P是从该值的类型推导的。
因此,当我们尝试匹配S<int const, nullptr>部分特化时,我们T从两个来源推导出部分特化的模板参数:
int const,我们推导出T=int constvoid (*)(int),因为函数参数的顶级 cv 限定被调整掉),我们推导出T= int。由于我们推导出了相互矛盾的结果,因此推导失败并且部分特化不匹配。
早在 2019 年,核心反射器就提出了类似的例子。人们一致认为这是标准中的一个缺陷,并且从非类型模板参数的类型中进行推导应该只发生在那些无法以其他方式推导的事情上。
| 归档时间: |
|
| 查看次数: |
220 次 |
| 最近记录: |