The following code compiles with g++ -std=c++11
but not with clang++ -std=c++11
.
Compile with g++ -std=c++11 main.cpp
and clang++ -std=c++11 main.cpp
. I am using GCC 4.8 and Clang 6.0.0 (trunk).
#include <iostream>
#include <vector>
enum Dir { LEFT, RIGHT };
int main(int argc, char** argv) {
// Interesting line: Notice the single ':'
std::vector<Dir> dirs = { Dir:LEFT, Dir:RIGHT };
for (auto v: dirs) {
std::cout << v << std::endl;
}
return 0;
}
For completeness and search-ability:
$ clang++ -std=c++11 main.cpp
main.cpp:7:29: warning: use of GNU old-style field designator extension [-Wgnu-designator]
std::vector<Dir> dirs = { Dir:LEFT, Dir:RIGHT };
^~~~
.Dir =
main.cpp:7:39: warning: use of GNU old-style field designator extension [-Wgnu-designator]
std::vector<Dir> dirs = { Dir:LEFT, Dir:RIGHT };
^~~~
.Dir =
main.cpp:7:20: error: no matching constructor for initialization of 'std::vector<Dir>'
std::vector<Dir> dirs = { Dir:LEFT, Dir:RIGHT };
^ ~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:269:7: note: candidate constructor not viable: cannot convert argument of incomplete type 'void' to 'std::vector::size_type' (aka 'unsigned long') for 1st argument
vector(size_type __n, const allocator_type& __a = allocator_type())
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:281:7: note: candidate constructor not viable: cannot convert argument of incomplete type 'void' to 'std::vector::size_type' (aka 'unsigned long') for 1st argument
vector(size_type __n, const value_type& __value,
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:331:7: note: candidate constructor not viable: cannot convert argument of incomplete type 'void' to 'const std::vector<Dir, std::allocator<Dir> >' for 1st argument
vector(const vector& __x, const allocator_type& __a)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:340:7: note: candidate constructor not viable: cannot convert argument of incomplete type 'void' to 'std::vector<Dir, std::allocator<Dir> >' for 1st argument
vector(vector&& __rv, const allocator_type& __m)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:364:7: note: candidate constructor not viable: cannot convert argument of incomplete type 'void' to 'initializer_list<std::vector<Dir, std::allocator<Dir> >::value_type>'
(aka 'initializer_list<Dir>') for 1st argument
vector(initializer_list<value_type> __l,
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:392:9: note: candidate template ignored: substitution failure [with _InputIterator = void]: no type named 'iterator_category' in 'std::iterator_traits<void>'
vector(_InputIterator __first, _InputIterator __last,
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:256:7: note: candidate constructor not viable: requires single argument '__a', but 2 arguments were provided
vector(const allocator_type& __a)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:310:7: note: candidate constructor not viable: requires single argument '__x', but 2 arguments were provided
vector(const vector& __x)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:327:7: note: candidate constructor not viable: requires single argument '__x', but 2 arguments were provided
vector(vector&& __x) noexcept
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_vector.h:248:7: note: candidate constructor not viable: requires 0 arguments, but 2 were provided
vector()
^
2 warnings and 1 error generated.
To cause gcc to reject the code, use -pedantic
switch.
The colon is an extension in GNU mode: X:Y
means .X = Y
, which is a designated initializer. (Neither of these are supported in ISO C++).
gcc also accepts the following code:
std::vector<int> v = { .a = 1, .b = 2 };
but rejects the code:
struct S { int p, q; S() {} };
S s = { .a = 1, .b = 2 }; // S has no member named 'a'
I guess this is a compiler bug; something about initializing a std::vector<int>
causes it to ignore the names of the designated initializers. Note, this sort of thing is a hallmark of non-standard features: often the very reason they aren't in the standard is that they didn't mix well with other language features and nobody could come up with a sensible proposal to handle all possible cases.
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