【问题标题】:No error for negative-size array负大小数组没有错误
【发布时间】:2016-09-14 09:22:08
【问题描述】:

为什么我在尝试创建负大小数组时不会出错?

#include <array>

int main()
{
    std::array<int, -1> arr;
}

-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC 我没有错误。这是预期的行为吗?

【问题讨论】:

  • 您使用的是哪个编译器?我使用 gcc 5.3.1 时出现错误“变量‘arr’的大小太大”

标签: c++ arrays c++11 stdarray


【解决方案1】:

不,这是不合法的。 std::array 的规范并没有明确阻止这种情况,但由于缩小了转换范围,这是非法的。

§14.3.2/5:

对于整数或枚举类型的非类型模板参数,转换 应用转换后的常量表达式 (5.19) 中允许的。

§5.19/3:

类型 T 的转换后的常量表达式是文字常量表达式, 隐式转换为 T 类型,其中隐式转换(如果有)是 在文字常量表达式和隐式转换序列中允许 仅包含用户定义的转换、左值到右值的转换 (4.1)、 积分提升(4.5)和积分转换(4.7),而不是缩小 转化次数 (8.5.4)

让 GCC 抱怨的唯一方法是启用 -Wsign-conversion。这是known bug,他们没有采取任何行动来修复它。

在 Clang 中,您会收到预期的错误消息:

error: non-type template argument evaluates to -1, which cannot be 
narrowed to type 'std::size_t' (aka 'unsigned long') [-Wc++11-narrowing]
    std::array<int, -1> arr;

【讨论】:

  • 历史记录:在已发布的 C++11 中,这是否是缩小转换由实现定义,但 DR 1449 已将其修复为始终缩小
【解决方案2】:

std::array 的类型是:

template< 
    class T, 
    std::size_t N 
> struct array;

当您使用-1 初始化第二个模板参数时,它会隐式转换为一个非常大的值,因为std::size_tunsigned(这在C++ 中是非法的,正如other answer 所指出的那样,它应该被诊断出来)。

另一种可能性是您的arr 已优化。您可以通过在 gcc 命令行中添加 -fdump-tree-optimized 标志来确认这一点。

如果你确保arr没有被优化出来,我希望你应该得到following warning

prog.cpp:5:25: error: size of variable 'arr' is too large
     std::array<int, -1> arr;

【讨论】:

  • 在这样的警告检查之后不会进行优化吗?
  • @BartoszKP 我使用了gcc --std=c++11 -O2 -fdump-tree-optimized arr_que.cpp,并确认代码已优化为return 0;,正如您所料。我不确定是否必须诊断模板参数滥用。
猜你喜欢
  • 2020-07-22
  • 1970-01-01
  • 2018-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-18
  • 2015-05-13
  • 1970-01-01
相关资源
最近更新 更多