Неверное поведение инициализации массива 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
) или просто простой ошибке?
Ответы
Ответ 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, этот отчет об ошибках, по-видимому, связан. Похоже, я пропустил это в первый раз, потому что название говорило о строковых литералах.