类模板部分专用化:编译器错误
Class template partial specialization: compiler error
这个程序
#include <iostream>
template <int I>
struct A
{
A() { std::cout << "A<I>()n"; }
};
template <int I>
struct A<I + 5>
{
A() { std::cout << "A<I + 5>()n"; }
};
int main()
{
return 0;
}
既不是由 gcc HEAD 10.0.020190 编译,也不是由 clang HEAD 10.0.0 编译。
例如 gcc 编译器发出错误
prog.cc:10:8: error: template argument '(I + 5)' involves template parameter(s)
10 | struct A<I + 5>
| ^~~~~~~~
是否存在错误的类模板部分专用化?
这不是有效的部分特化(尽管错误可能会更好(。我们不遵守的条款如下:
[温度.class规格]
8 类模板部分的参数列表内 专业化,以下限制适用:
- 专业化应比主要模板更专业。
"专业化不是更专业!?"我想你会想的。但事实确实如此。确定哪个"更专业"的规则在[temp.class.order]中描述。它的要点是我们要考虑两个假设的函数模板重载:
template <int I>
struct A { /* ... */ };
template<int I>
void foo(A<I>); //1
template<int I>
void foo(A<I + 5>); //2
然后,我们对函数模板执行重载解析和部分排序。如果#2获胜,它更专业,您的声明是合法的。如果未获胜,则声明无效。部分排序是通过制作一些参数并执行一个模板对另一个模板的模板参数推导来完成的。因此,假设我们首先比较第一个和第二个(为简单起见,我将重命名它们,但它们仍然是重载(:
void foo1(A<0>); -> void foo2(A<I + 5>);
论点演绎在这里成功吗?其实不然。I + 5
是一个非推导的上下文:
[温度扣除类型]
非推导上下文是:
5.3 - 非类型模板参数或数组绑定 子表达式引用模板参数。
I
引用模板参数,因此I + 5
是非推导上下文。因此,模板参数推导在这个方向上失败。
让我们尝试另一个方向。我们再次制造一个论点
void foo2(A<1 + 5>); = void foo2(A<6>); -> void foo1(A<I>);
演绎显然在这里成功了。所以根据函数模板部分排序的规则,foo1
比foo2
更专业。这意味着我们的初级实际上比我们的"部分专业化"更专业,使得部分专业化形成错误。
查看 temp.class.spec.match/3,我们有
如果由于模板参数列表和模板 id的结构而无法推断出部分专用化的模板参数,则程序格式不正确。
以示例
template <int I, int J> struct A {};
template <int I> struct A<I+5, I*2> {}; // error
template <int I> struct A<I, I> {}; // OK
template <int I, int J, int K> struct B {};
template <int I> struct B<I, I*2, 2> {}; // OK
Clang的错误消息与此相呼应:
error: class template partial specialization contains a template parameter that cannot be deduced; this partial specialization will never be used
(请参阅@StoryTeller的答案,了解为什么此推论在您的代码中失败,我不会在这里重复它。
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++,我收到一个无法理解的编译器错误
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- 重载方法的方式会在使用临时调用时生成编译器错误
- 尝试使用继承和模板实现CRTP.Visual Studio正在生成编译器错误
- 编译器错误:destuctor 的更宽松的抛出说明符
- Android NDK clang 编译器错误在 Windows 上显示'No such file or directory'
- C++ G++ 编译器 - 错误:隐式声明的定义
- 这个失败的测试是将零添加到空指针未定义的行为、编译器错误还是其他什么?
- 模板模板参数和模板别名:编译器错误?
- C++ 编译器错误:P1LinkedList.cpp:145:错误:重载的"to_string(int&)"调用不明确
- 在gcc中意外调用了Const重载.编译器错误或兼容性修复程序
- C1001内部编译器错误是由于矢量初始化(如数组)引起的
- 编译器错误(英特尔并行工作室 2019 与 Visual Studio 社区 2019)
- 如何在C++中克服此 C4430 编译器错误?
- 尝试使用 WinBGI 显示文本时出现编译器错误
- 使用typedef'ed返回类型声明友元函数时出现编译器错误
- 如何在类模板的成员函数中正确调用函数对象?正在生成 Visual Studio 编译器错误 C2440
- C++自定义分配器大小参数作为模板参数会引发编译器错误