Clang vs GCC:Enum使用中的单冒号

时间:2017-07-24 13:57:07

标签: c++ gcc enums g++ clang++

以下代码使用g++ -std=c++11进行编译,但不使用clang++ -std=c++11进行编译。

问题

  1. 在这种情况下,单冒号“运算符”的含义是什么?
    • 澄清/编辑:GCC如何解释代码?
  2. 如何让GCC不编译此代码? (假设Clang遵循C ++标准。)这是否有标志?
  3. 代码

    使用g++ -std=c++11 main.cppclang++ -std=c++11 main.cpp进行汇编。我正在使用GCC 4.8和Clang 6.0.0(主干)。

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

    Clang错误消息

    为了完整性和可搜索性:

     $ 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.
    

1 个答案:

答案 0 :(得分:7)

要使gcc拒绝代码,请使用-pedantic开关。

冒号是GNU模式的扩展:X:Y表示.X = Y,它是指定的初始化程序。 (ISO C ++不支持这些)。

gcc也接受以下代码:

std::vector<int> v = { .a = 1, .b = 2 };

但拒绝代码:

struct S { int p, q; S() {} };
S s = { .a = 1, .b = 2 };   // S has no member named 'a'

我猜这是编译错误;有关初始化std::vector<int>的事情会导致它忽略指定初始值设定项的名称。请注意,这种事情是非标准功能的标志:通常他们不在标准中的原因是他们没有与其他语言功能很好地混合,没有人能够提出一个明智的建议来处理所有可能的情况。