成员数组的大小由模板参数定义,但为什么没有针对零大小数组的警告?

doc*_*7b5 5 c++ arrays templates

我试图编写一个模板化的基类来存储固定数量的数据类型,每个数据类型的长度各不相同.这是我尝试做的很多简化版本:

template< int NINT, int NR0 >
class EncapsulatedObjectBase
{
   public:

  EncapsulatedObjectBase();

  ~EncapsulatedObjectBase();

  double m_real[NR0];
  int m_int[NINT];
}
Run Code Online (Sandbox Code Playgroud)

是的...所以模板参数可以为零,从而声明一个零长度的对象数组.这个库将有多个派生类,每个派生类定义自己的变量数.我有两个问题:

1)这种方法是否存在根本缺陷?

2)如果是这样的话...当我实例化零长度数组时,为什么icc13或gcc4.7.2没有给我警告?对于gcc我使用-wall和-wextra -wabi.缺乏警告让我觉得这种事情还行.

编辑:

以下是显示我正在谈论的文件的内容:

#include <iostream>

template< int NINT, int NR0 >
class EncapsulatedObjectBase
{
public:
  EncapsulatedObjectBase(){}
  ~EncapsulatedObjectBase(){}

  double m_real[NR0];
  int m_int[NINT];
};


class DerivedDataObject1 : public EncapsulatedObjectBase<2,0>
{
   public:

   DerivedDataObject1(){}

  ~DerivedDataObject1(){}

  inline int& intvar1() { return this->m_int[0]; }
  inline int& intvar2() { return this->m_int[1]; }

};


class DerivedDataObject2 : public EncapsulatedObjectBase<0,2>
{
   public:

   DerivedDataObject2(){}

  ~DerivedDataObject2(){}

  inline double& realvar1() { return this->m_real[0]; }
  inline double& realvar2() { return this->m_real[1]; }
};




int main()
{
   DerivedDataObject1 obj1;
   DerivedDataObject2 obj2;

   obj1.intvar1() = 12;
   obj1.intvar2() = 5;

   obj2.realvar1() = 1.0e5;
   obj2.realvar2() = 1.0e6;

   std::cout<<"obj1.intvar1()  = "<<obj1.intvar1()<<std::endl;
   std::cout<<"obj1.intvar2()  = "<<obj1.intvar2()<<std::endl;
   std::cout<<"obj2.realvar1() = "<<obj2.realvar1()<<std::endl;
   std::cout<<"obj2.realvar2() = "<<obj2.realvar2()<<std::endl;


}
Run Code Online (Sandbox Code Playgroud)

如果我用"g ++ -Wall -Wextra -Wabi main.cpp"编译它,我没有得到任何警告.我必须使用-pedantic标志来获取警告.所以我仍然不知道这是多么不安全.回想起来,我觉得它一定不是一个好主意......虽然如果我能逃脱它会非常有用.

Lig*_*ica 3

零大小的数组在 C++ 中实际上是非法的:

\n\n
\n

[C++11: 8.3.4/1]: [..]如果存在常量表达式(5.19),则它应为整型常量表达式,并且其值应大于零。常量表达式指定数组(元素数量)的界限。如果常量表达式的值为N,则数组的N元素编号0N-1,且 的标识符类型为T D\xe2\x80\x9d的\xe2\x80\x9c派生声明符类型列表数组。N[..]

\n
\n\n

因此,您的类模板无法0,0 使用 GCC 4.1.2 中的参数实例化,也无法在 GCC 4.7.2 中使用合理的标志进行实例化:

\n\n
template< int NINT, int NR0 >\nclass EncapsulatedObjectBase\n{\n   public:\n\n  EncapsulatedObjectBase();\n\n  ~EncapsulatedObjectBase();\n\n  double m_real[NR0];\n  int m_int[NINT];\n};\n\nint main()\n{\n   EncapsulatedObjectBase<0,0> obj;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

t.cpp:在 \'EncapsulatedObjectBase<0, 0>\' 的实例化中:
\n t.cpp:17:从此处实例化
\n 第 10 行:错误:ISO C++ 禁止零大小数组
\n 编译由于 - 终止致命错误。

\n
\n\n

铿锵 3.2 说:

\n\n
\n

source.cpp:10:17:警告:零大小数组是扩展 [-Wzero-length-array]

\n
\n\n

(请注意,无论如何,在尝试实例化这样的类之前,您不会收到任何错误。)

\n\n

那么,这是一个好主意吗?不,不是真的。我建议当任一参数为 时,禁止类模板的实例化0。我还会了解为什么您想要零长度数组并考虑调整您的设计。

\n

  • 它是非法的,但可以使用 G++ 的默认选项实例化(如您自己的 liveworkspace 输出所示)。您应该清楚,当您说“合理标志”时,您指的是“-pedantic-errors -Wfatal-errors”,许多人认为这对于一般用途来说是不合理的。 (3认同)