I was using gcc 4.8 until I upgraded Ubuntu, now I have gcc-4.9.1-16. Code which used to compile without warnings and run fine now no longer compiles.
static const unsigned WIDTH = 16;
static const unsigned VSCALE = 1;
static const unsigned HEIGHT = WIDTH / VSCALE;
static const unsigned FOOTER = 2;
typedef char Row [WIDTH + 1];
typedef Row World [HEIGHT - FOOTER];
std :: vector <World> m_levels;
World levels [] =
{
{
" ",
" ",
" ",
" ",
" ",
" ### ### ",
" ",
"1122112211221122",
" 33003300330033 ",
"1122112211221122",
" 33003300330033 ",
" ",
" ",
" "
},
{
" 44 ",
" 555 55 ",
" 66 66 ",
" 777 777 ",
" 66 66 ",
" 777 777 ",
" 66# #66 ",
" 777 # # 777 ",
" 66 # # 66 ",
" 777 # # 777 ",
" 66# #66 ",
" 555 55 ",
" 44 ",
" "
}
};
// The next line is line 68
m_levels .assign (std :: begin (levels), std :: end (levels));
The final line errors with
.../foo.cpp:68:62: required from here /usr/include/c++/4.9/bits/stl_algobase.h:373:4: error: static assertion failed: type is not assignable
.../foo.cpp:68:62: required from here /usr/include/c++/4.9/bits/stl_construct.h:75:7: error: parenthesized initializer in array new [-fpermissive]
The compile options have not changed, they are -W -Wall -Wextra -Werror -pedantic --std=c++0x
as far as I can tell only gcc has changed.
Why does this code no longer compile?
The bare minimum requirement on value types for standard containers is that they must be Erasable
. For the default allocator, this translates to the requirement that given value_type *p;
, p->~value_type();
must be well-formed.
If value_type
is a class type, it simply invokes the destructor, and is well-formed if the destructor is not deleted and is accessible. If value_type
denotes a scalar type, p->~value_type();
is also valid and a no-op (this is called a pseudo destructor call). However, if value_type
is an array type, then p->~value_type();
is invalid.
Hence, built-in arrays are never valid value types for standard containers, at least when the default allocator is used. (Various other container operations place more requirements on the value type; built-in arrays would run afoul of at least some of them since they are not assignable.)
Instantiating a standard library template with types that do not satisfy the requirements of that template results in undefined behavior. It appears that libstdc++ by happenstance didn't diagnose your error until the version that shipped with GCC 4.9.
The fix, by the way, is simple. Just use std::array
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With