【问题标题】:Clang vs GCC: Single-colon in Enum usageClang vs GCC:枚举使用中的单冒号
【发布时间】:2017-07-24 13:57:06
【问题描述】:

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

问题

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

代码

使用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.

【问题讨论】:

  • 这看起来像是糟糕的代码。你可以有enum class Dir { LEFT, RIGHT };,然后是std::vector&lt;Dir&gt; dirs = { Dir::LEFT, Dir::RIGHT };,但这不是正确的代码。
  • @NathanOliver:这是糟糕的代码!但这就是问题 2 的内容:如何让 GCC 不编译它。感谢 M.M 的旗帜。
  • 糟糕。对于那个很抱歉。没有看到 gcc 实际编译。继续前进

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


【解决方案1】:

要让 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&lt;int&gt; 的一些事情会导致它忽略指定初始化程序的名称。请注意,这类事情是非标准特性的标志:它们不在标准中的原因通常是它们没有与其他语言特性很好地融合在一起,没有人能提出一个明智的建议来处理所有可能的情况。

【讨论】:

    猜你喜欢
    • 2011-08-30
    • 2021-10-21
    • 2020-01-18
    • 2018-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    相关资源
    最近更新 更多