【问题标题】:Implicit type conversion between size_t and int using templates使用模板在 size_t 和 int 之间进行隐式类型转换
【发布时间】:2019-11-05 08:21:40
【问题描述】:

我有这个编译时序列生成类(取自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...> {

将标记行中的size_t类型(标记为XXX (read below))改成int后,大家就可以正确编译这个示例代码了。

在这种情况下谁是对的? Visual Studio 是因为它编译代码,还是 GCC+Clang 因为它不允许编译?

为什么 Visual Studio 能够很好地编译示例?它是否比其他编译器具有更宽松的隐式转换规则?还是有其他原因?任何可以将我指向可以帮助我解码这些错误消息的文档的链接也将不胜感激:)

【问题讨论】:

标签: c++ language-lawyer variadic-templates implicit-conversion template-specialization


【解决方案1】:

这是由于活动语言缺陷CWG issue 1647:

标准似乎对部分特化中的非类型模板参数的类型是否必须与主模板的类型相同或是否允许转换保持沉默

对此的处理存在实现差异...

所以这里没有合适的编译器,因为标准中没有明确的要求如何处理这些特化。

请注意,GCC 和 Clang 由于不同的原因而出现分歧并导致此示例失败。演示:https://gcc.godbolt.org/z/41cbPePPW

Clang 不能偏爱以下两种专业之一:

error: ambiguous partial specializations of 'generator<0, 0, 1, 2, 3, 4>'

而且 GCC 完全忽略了特化 struct generator&lt;Count, Ns...&gt; 试图实例化主模板并由于缺少其定义而失败:

error: invalid use of incomplete type 'struct generator<5>'

在 GCC 中,2014 年报告了相应的错误 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60679),目前处于等待 C++ 标准澄清的状态。

正如问题所说,用int替换size_t是最好的,解决所有问题,演示:https://gcc.godbolt.org/z/fY9hxsT7P

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    相关资源
    最近更新 更多