Подтвердить что ты не робот

Неверное поведение инициализации массива GCC

Я столкнулся с вариантом этого кода при просмотре другого вопроса (исходный код использовал std::thread вместо std::vector, но синтаксис тот же):

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main()
{
    std::vector<double> vecs[10] = std::vector<double>(10, 1);
    for(auto& vec: vecs){
        std::copy(vec.begin(), vec.end(), std::ostream_iterator<double>(std::cout, " "));
        std::cout<<std::endl;
    }
    return 0;
}

Этот код не должен компилироваться; std::vector<double> vecs[10] = std::vector<double>(10, 1); недействителен синтаксис инициализации, а clang отклоняет его с помощью error: array initializer must be an initializer list. Однако GCC принимает его и появляется для инициализации каждого вектора в списке с копией указанного временного.

Является ли это некоторым расширением GCC, о котором я никогда не слышал (которому так или иначе удалось выжить -pedantic-errors) или просто простой ошибке?

4b9b3361

Ответ 1

Я считаю это ошибкой.

#include <vector>

int main()
{
  std::vector<double> x = std::vector<double>(10, 1);
  std::vector<double> vecs[10] = x;
  return 0;
}

Работает (как вы заметили).

В то время как

int main()
{
  int x = 10;
  int is[10] = x;
  return 0;
}

дает (ожидаемую) ошибку.

Ответ 2

Дальнейшие исследования:

struct A { A() { } };
int main() { A a[10] = A(); }

Это компилируется в GCC.

struct A { A() = default; };
int main() { A a[10] = A(); }

Также компилируется в GCC 4.9, но не более ранних версиях, которые я тестировал (4.6-4.8).

struct A { };
int main() { A a[10] = A(); }

Не компилируется.

struct B { virtual ~B() { } };
struct A : B { };
int main() { A a[10] = A(); }

Собирает.

struct B {  ~B() { } };
struct A : B { };
int main() { A a[10] = A(); }

Не компилируется.

Я думаю, что можно с уверенностью сказать, что это ошибка. Никакое нормальное расширение не будет иметь такого рода поведение. Обратите внимание, что A как во втором случае, так и в третьем случае являются типами POD (единственная разница - явно установленный по умолчанию конструктор по умолчанию), но они обрабатываются по-разному с помощью GCC 4.9.

Изменить: снова в GCC bugzilla, этот отчет об ошибках, по-видимому, связан. Похоже, я пропустил это в первый раз, потому что название говорило о строковых литералах.