20

I encountered a variant of this code when looking at another question (the original code used a std::thread instead of std::vector, but the syntax is the same):

#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;
}

This code shouldn't compile; std::vector<double> vecs[10] = std::vector<double>(10, 1); is not valid initialization syntax, and clang rejects it with error: array initializer must be an initializer list. However, GCC accepts it and appears to initialize every vector in the list with a copy of the specified temporary.

Is this some GCC extension I've never heard about (that somehow also managed to survive -pedantic-errors) or just a plain bug?

7
  • I'm guessing difference in language standard? Commented Jun 24, 2014 at 5:31
  • @JonathonReinhart Both are in C++11 mode, and AFAIK that syntax has never been legal in C++. Commented Jun 24, 2014 at 5:39
  • Is this not the (2) fill constructor, as mentioned here? Edit: Ah nevermind, missed the array in your variable declaration. Commented Jun 24, 2014 at 5:42
  • @JonathonReinhart Yes, that's a valid constructor, the problem is the attempt to use that to initialize the array. That should not compile. Commented Jun 24, 2014 at 5:44
  • 2
    Minimal example: struct a {a();} x[2] = a();. gcc compiles it. Without the constructor declaration, it won't. Clearly a bug. Commented Jun 24, 2014 at 17:35

2 Answers 2

4

I would consider this a bug.

#include <vector>

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

Works (as you have spotted).

While

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

yields the (expected) error.

Sign up to request clarification or add additional context in comments.

Comments

2

Further investigation:

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

This compiles in GCC.

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

Also compiles in GCC 4.9 but not earlier versions I tested (4.6-4.8).

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

Doesn't compile.

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

Compiles.

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

Doesn't compile.

I think it's safe to say that it's a bug. No sane extension would have this sort of behavior. Note that A in both the second case and the third case are POD types (the only difference being an explicitly defaulted default constructor), but they are treated differently by GCC 4.9.

Edit: Going through the GCC bugzilla again, this bug report appears to be related. Looks like I missed it the first time through because the title was talking about string literals.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.