使用模板在 size_t 和 int 之间进行隐式类型转换
Implicit type conversion between size_t and int using templates
我有这个编译时序列生成class(取自here,并稍微修改了一下):
#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;
}
这在 Visual Studio 下编译得很好(即使使用 /permissive-
开关)。但它在 GCC 下抛出错误:
g++: error: template argument '(int)Count' involves template parameter(s)
g++: struct generator<Count, Ns...> {
...
它在 Clang 下也会抛出错误:
clang++: error: ambiguous partial specializations of 'generator<0, 0, 1, 2, 3, 4>'
clang++: using type = typename generator<Count - 1, Count - 1, Ns...>::type;
...
clang++: note: partial specialization matches [with Count = 0, Ns = <0, 1, 2, 3, 4>]
clang++: struct generator<Count, Ns...> {
clang++:
clang++: note: partial specialization matches [with Ns = <0, 1, 2, 3, 4>]
clang++: struct generator<0, Ns...> {
将标记行(标记为XXX (read below)
)中的size_t
类型改为int
后,大家可以正确编译此示例代码。
在这种情况下谁是对的? Visual Studio 因为它编译代码,还是 GCC+Clang 因为它不允许编译?
为什么Visual Studio能够编译出样例呢?它有比其他编译器更宽松的隐式转换规则吗?还是有其他原因?任何 link 指向可以帮助我解码这些错误消息的文档也将不胜感激 :)
这是由于活动语言缺陷CWG issue 1647:
The Standard appears to be silent on whether the types of non-type template arguments in a partial specialization must be the same as those of the primary template or whether conversions are permitted
There is implementation variance in the treatment of this...
所以这里没有正确的编译器,因为标准中没有明确要求如何处理此类专业化。
请注意,由于不同的原因,GCC 和 Clang 出现分歧并导致此示例失败。演示:https://gcc.godbolt.org/z/41cbPePPW
Clang 不能偏爱两个专业之一:
error: ambiguous partial specializations of 'generator<0, 0, 1, 2, 3, 4>'
并且 GCC 完全忽略了专业化 struct generator<Count, Ns...>
尝试实例化主模板并由于缺少其定义而失败:
error: invalid use of incomplete type 'struct generator<5>'
在 GCC 中,2014 年报告了相应的错误 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60679),目前处于等待 C++ 标准澄清的状态。
如问题所说,这里把size_t
换成int
最好,解决所有问题,demo:https://gcc.godbolt.org/z/fY9hxsT7P
我有这个编译时序列生成class(取自here,并稍微修改了一下):
#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;
}
这在 Visual Studio 下编译得很好(即使使用 /permissive-
开关)。但它在 GCC 下抛出错误:
g++: error: template argument '(int)Count' involves template parameter(s)
g++: struct generator<Count, Ns...> {
...
它在 Clang 下也会抛出错误:
clang++: error: ambiguous partial specializations of 'generator<0, 0, 1, 2, 3, 4>'
clang++: using type = typename generator<Count - 1, Count - 1, Ns...>::type;
...
clang++: note: partial specialization matches [with Count = 0, Ns = <0, 1, 2, 3, 4>]
clang++: struct generator<Count, Ns...> {
clang++:
clang++: note: partial specialization matches [with Ns = <0, 1, 2, 3, 4>]
clang++: struct generator<0, Ns...> {
将标记行(标记为XXX (read below)
)中的size_t
类型改为int
后,大家可以正确编译此示例代码。
在这种情况下谁是对的? Visual Studio 因为它编译代码,还是 GCC+Clang 因为它不允许编译?
为什么Visual Studio能够编译出样例呢?它有比其他编译器更宽松的隐式转换规则吗?还是有其他原因?任何 link 指向可以帮助我解码这些错误消息的文档也将不胜感激 :)
这是由于活动语言缺陷CWG issue 1647:
The Standard appears to be silent on whether the types of non-type template arguments in a partial specialization must be the same as those of the primary template or whether conversions are permitted
There is implementation variance in the treatment of this...
所以这里没有正确的编译器,因为标准中没有明确要求如何处理此类专业化。
请注意,由于不同的原因,GCC 和 Clang 出现分歧并导致此示例失败。演示:https://gcc.godbolt.org/z/41cbPePPW
Clang 不能偏爱两个专业之一:
error: ambiguous partial specializations of 'generator<0, 0, 1, 2, 3, 4>'
并且 GCC 完全忽略了专业化 struct generator<Count, Ns...>
尝试实例化主模板并由于缺少其定义而失败:
error: invalid use of incomplete type 'struct generator<5>'
在 GCC 中,2014 年报告了相应的错误 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60679),目前处于等待 C++ 标准澄清的状态。
如问题所说,这里把size_t
换成int
最好,解决所有问题,demo:https://gcc.godbolt.org/z/fY9hxsT7P