ant*_*one 5 c++ template-specialization language-lawyer implicit-conversion variadic-templates
我有这个编译时序列生成类(取自此处,并对其进行了一些修改):
#include <cstddef>
template <int...>
struct sequence {};
template <int... Ns>
struct generator;
template <std::size_t Count, int... Ns> // XXX (read below)
struct generator<Count, Ns...> {
using type = typename generator<Count - 1, Count - 1, Ns...>::type;
};
template <int... Ns>
struct generator<0, Ns...> {
using type = sequence<Ns...>;
};
template <std::size_t N>
using sequence_t = typename generator<N>::type;
int main() {
sequence_t<5> a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这在 Visual Studio 下编译得很好(即使使用/permissive-开关)。但在 GCC 下会抛出错误:
#include <cstddef>
template <int...>
struct sequence {};
template <int... Ns>
struct generator;
template <std::size_t Count, int... Ns> // XXX (read below)
struct generator<Count, Ns...> {
using type = typename generator<Count - 1, Count - 1, Ns...>::type;
};
template <int... Ns>
struct generator<0, Ns...> {
using type = sequence<Ns...>;
};
template <std::size_t N>
using sequence_t = typename generator<N>::type;
int main() {
sequence_t<5> a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它也会在 Clang 下抛出错误:
g++: error: template argument '(int)Count' involves template parameter(s)
g++: struct generator<Count, Ns...> {
...
Run Code Online (Sandbox Code Playgroud)
size_t将标记行(标记为XXX (read below))中的类型更改为 后int,每个人都可以正确编译此示例代码。
在这种情况下谁是对的?Visual Studio 因为它编译代码,还是 GCC+Clang 因为它不允许编译?
为什么 Visual Studio 能够很好地编译示例?它是否比其他编译器有更宽松的隐式转换规则?或者有什么不同的原因吗?任何将我指向可以帮助我解码这些错误消息的文档的链接也将不胜感激:)
这是由于活动语言缺陷CWG 问题 1647造成的:
该标准似乎没有明确说明部分特化中的非类型模板参数的类型是否必须与主模板的类型相同或是否允许转换
对此的处理存在实施差异......
因此,这里没有正确的编译器,因为标准中没有明确要求如何处理此类专业化。
请注意,GCC 和 Clang 存在分歧,并且由于不同的原因导致此示例失败。演示: https: //gcc.godbolt.org/z/41cbPePPW
Clang 不能选择以下两个专业之一:
error: ambiguous partial specializations of 'generator<0, 0, 1, 2, 3, 4>'
Run Code Online (Sandbox Code Playgroud)
struct generator<Count, Ns...>GCC 完全忽略了尝试实例化主模板并由于缺乏定义而失败的专业化:
error: invalid use of incomplete type 'struct generator<5>'
Run Code Online (Sandbox Code Playgroud)
在 GCC 中,相应的 bug 于 2014 年报告(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60679),目前处于搁置状态,等待 C++ 标准澄清。
size_t正如问题所说,这里用with替换int是最好的,解决了所有问题,demo: https: //gcc.godbolt.org/z/fY9hxsT7P