允许std :: vector <c_type_array> </c_type_array>的g ++ 4.9错误

时间:2014-08-03 21:01:36

标签: c++ c++11 stl gcc4.9

请考虑以下代码:

#include <iostream>
#include <vector>
#include <array>

using namespace std;

typedef double (C_array)[10];

int main()
{ 
    std::vector<C_array> arr(10);

    // let's initialize it
    for (int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++)
            arr[i][j] = -1;

    // now make sure we did the right thing
    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}

我刚刚从@juanchopanza https://stackoverflow.com/a/25108679/3093378发现这段代码不合法​​,因为普通的旧C - 样式数组不可分配/可复制/可移动。但是,即使使用g++-Wall -Wextra -pedantic也会通过代码。 clang++无法编译它。当然,如果我尝试执行auto arr1 = arr;之类的操作,它会在g++下失败,因为它不知道如何将arr复制到arr1

我在OS X Mavericks下使用了来自g++4.9的{​​{1}}。 这里的实时代码:http://goo.gl/97koLa

我的问题是:

  1. 根据标准,此代码是否违法?
  2. macports是如此错误?我一直在寻找许多简单的例子,其中g++盲目地编译非法代码,最后一次是昨天user-defined conversion operators precedence, compiles in g++ but not clang++,并且没有太多努力,只是为了好玩而尝试g++

1 个答案:

答案 0 :(得分:2)

您的代码无效C ++ 03。首先,标头<array>不是C ++ 03标准库的一部分,但这里也不需要它。其次,vector对象的构造试图调用构造函数

explicit vector(size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type());

但是,val的初始化失败的原因与您无法编写

的原因相同
C_array foo = C_array();

据我所知,C ++ 03标准第5.2.3节中的第2段仅允许这种表示法用于非数组类型:

  

表达式T(),其中T是非数组完整对象类型的简单类型说明符(7.1.5.2)或(可能是cv限定的)void类型,它创建指定类型的rvalue,这是值初始化的(8.5;没有为void()情况进行初始化)。

此外,g ++ - 4.9.0也拒绝编译代码,除非在命令行中提供了-std = c ++ 11:

foo.cpp: In constructor ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = double [10]; _Alloc = std::allocator<double [10]>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = double [10]; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<double [10]>]’:
foo.cpp:11:32: error: functional cast to array type ‘std::vector<double [10]>::value_type {aka double [10]}’
 std::vector<C_array> arr(10);
...

对于C ++ 11,向量容器提供了一个额外的填充构造函数:

explicit vector (size_type n);

此构造函数要求模板类型是可默认构造的(请参阅第23.3.6.2节)。据我所知,在C ++ 11中也没有满足这个要求(参见17.6.3.1节),因为为了满足要求,表达式C_array()必须创建一个临时对象,这在C +中也是无效的。 +11(再次参见第5.2.3节)。我不知道标准是否实际上要求编译器拒绝代码,或者如果不满足其中一个要求但是标准库的实现不需要,则允许编译器编译它。也许那些了解C ++ 11的人可以填补这些空白。

除此之外,我认为尝试将数组用作容器元素类型并不是一个好主意,因为不满足其他容器要求。例如,C_array不是可复制插入的,因此无法复制向量。

关于您的第二个问题:请随意浏览https://gcc.gnu.org/bugzilla/处的gcc bugzilla数据库。但是,接受无效代码也可能是有目的的,例如为了不破坏遗留代码。