V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Betsy
V2EX  ›  C++

求教个简单的 C++ 语法问题

  •  
  •   Betsy · 2023-11-07 23:47:16 +08:00 · 1547 次点击
    这是一个创建于 379 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码如下

    #include<iostream>
    
    enum ExprValueType : uint8_t {
      MinInf = 1
    };
    
    int main(int argc, char* argv[]) {
      ExprValueType type = MinInf;
      std::cout <<"Hello world" << std::endl;
      std::cout << type << std::endl;
      return 0;
    }
    

    使用 g++ abc.cc -o a.out -std=c++20 报错,报错信息如下所示

    abc.cc:3:20: error: found ‘:’ in nested-name-specifier, expected ‘::’
        3 | enum ExprValueType : uint8_t {
          |                    ^
          |                    ::
    abc.cc:3:6: error: ‘ExprValueType’ has not been declared
        3 | enum ExprValueType : uint8_t {
          |      ^~~~~~~~~~~~~
    abc.cc:3:30: error: expected unqualified-id before ‘{’ token
        3 | enum ExprValueType : uint8_t {
          |                              ^
    abc.cc: In function ‘int main(int, char**)’:
    abc.cc:8:3: error: ‘ExprValueType’ was not declared in this scope
        8 |   ExprValueType type = MinInf;
          |   ^~~~~~~~~~~~~
    abc.cc:10:16: error: ‘type’ was not declared in this scope; did you mean ‘std::__cmp_cat::type’?
       10 |   std::cout << type << std::endl;
          |                ^~~~
          |                std::__cmp_cat::type
    In file included from /usr/include/c++/13/bits/char_traits.h:56,
                     from /usr/include/c++/13/ios:42,
                     from /usr/include/c++/13/ostream:40,
                     from /usr/include/c++/13/iostream:41,
                     from abc.cc:1:
    /usr/include/c++/13/compare:49:11: note: ‘std::__cmp_cat::type’ declared here
       49 |     using type = signed char;
          |           ^~~~
    

    个人猜测是 gcc 版本的问题,于是在 https://gcc.godbolt.org/ 切换不同的编译器查看。

    • 发现自 x86-64 gcc 13.1 开始会报错,之前版本(比如 x86-64 gcc 12.3)就不会报错。
    • 同样 x86-64 clang 17.0.1 开始会报错,之前版本(比如 x86-64 clang 16.0.0 )就不会报错。

    于是产生了两个困惑

    • 编译器最近是出了什么新的标准导致不支持 enum 的这种写法了吗?
    • 如果想要在 x86-64 gcc 13.1 上跑起来,应该怎么改?
    第 1 条附言  ·  2023-11-08 00:23:18 +08:00
    添加头文件 #include<cstdint> 后就正常了。

    但是为什么之前版本的 gcc 就不需要添加这个头文件呢?
    9 条回复    2023-11-08 22:59:15 +08:00
    xipuxiaoyehua
        1
    xipuxiaoyehua  
       2023-11-07 23:52:52 +08:00 via iPhone
    enum class ExprValueType : uint8_t {
    MinInf = 1
    };
    Betsy
        2
    Betsy  
    OP
       2023-11-08 00:03:35 +08:00 via iPhone
    @xipuxiaoyehua 不可以的,从 Unscoped enumerations 换成 Scoped enumerations 依然存在这个问题。
    geelaw
        3
    geelaw  
       2023-11-08 01:07:06 +08:00
    因为标准规定 std::uint8_t 在 cstdint 中定义。请注意直接用 uint8_t 也是错误的,能编译通过只是因为运气好。

    之前在 #include <iostream> 之后看起来可以用,大概是因为:

    1. 具体实现里的 iostream 间接包含了 cstdint ;且
    2. 具体实现里的 cstdint 也在全局命名空间里定义了 uint8_t 。

    这两件事不是必然成立,所以编译失败不稀奇。
    marat1ren
        4
    marat1ren  
       2023-11-08 01:08:16 +08:00 via iPhone
    感觉是需要 cstdint 里面定义的 uint8_t 。可以试试 std::unit8_t
    Betsy
        5
    Betsy  
    OP
       2023-11-08 01:19:49 +08:00 via iPhone
    @geelaw 这样子啊,感谢说明 🙏
    dangyuluo
        6
    dangyuluo  
       2023-11-08 02:39:47 +08:00
    dangyuluo
        7
    dangyuluo  
       2023-11-08 02:39:53 +08:00
    缺 uint8_t
    Betsy
        8
    Betsy  
    OP
       2023-11-08 22:56:14 +08:00 via iPhone
    @marat1ren
    @dangyuluo

    是的。经过确认不引入 cstdint ,直接 std::uint8_t 是不可以的
    Betsy
        9
    Betsy  
    OP
       2023-11-08 22:59:15 +08:00 via iPhone
    @dangyuluo 这个改动实在太骚气了 😅
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3032 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 13:58 · PVG 21:58 · LAX 05:58 · JFK 08:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.