自己写了一个 JSON 解析器,遇到一个问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fgwmlhdkkkw
V2EX    C++

自己写了一个 JSON 解析器,遇到一个问题

  •  
  •   fgwmlhdkkkw 2022-04-14 16:00:38 +08:00 2820 次点击
    这是一个创建于 1342 天前的主题,其中的信息可能已经有所发展或是发生改变。

    LlTXqS.png

    问题是,

    • C+是不是没有办法实现变长参数?
    • 图片里的这种方式最终是不是会变成很多个函数的相互调用?
    • 但我给每个函数都加了 inline ,会有什么影响吗?

    谢谢~

    18 条回复    2022-04-15 18:05:06 +08:00
    fgwmlhdkkkw
        1
    fgwmlhdkkkw  
    OP
       2022-04-14 16:08:36 +08:00
    有编译器会尝试把这种写法变成一个循环吗?
    codehz
        2
    codehz  
       2022-04-14 16:31:26 +08:00 via Android   1
    你写类定义里默认就是 inline ,用模板基本上逃不了 inline 了,然后 inline 的语义是允许在不同翻译单元重复定义,不是“不生成函数原地展开”,能不能展开看编译器心情
    lonewolfakela
        3
    lonewolfakela  
       2022-04-14 16:35:01 +08:00   1
    1 、你写的这个不就是变长参数?
    2 、是。
    3 、几乎没啥影响……可能让某些编译器的优化步骤中对函数内联稍微激进一点点,但是效果可以忽略不计。
    4 、尾递归确实很可能被优化掉,但是优化器的事情没人敢打包票;虽然我觉得如果你这个实际跑起来没啥问题的话就这样也挺好。
    5 、真要是觉得递归看起来实在难看的话,可以学习一下 https://en.cppreference.com/w/cpp/language/fold 的用法
    6 、你为什么不把变长参数放在一个 std::vector 里传进去呢……
    fgwmlhdkkkw
        4
    fgwmlhdkkkw  
    OP
       2022-04-14 16:48:55 +08:00
    @codehz #2 我一直以为 inline 是“尽可能的 define”。
    @lonewolfakela #3 谢谢,vector 的话,我要为数字和字符串做一个包装类。问题是在这个包装类里怎么储存字符串?(我不想复制)。
    cnbatch
        5
    cnbatch  
       2022-04-14 17:31:26 +08:00
    不想复制的话,可以使用万能引用、完美转发

    template <typename T, typename ... Args>
    [[nodiscard]]
    const Value * peek(const Value * src, T key, Args && ... args)
    {
    // auto 和 if 的部分
    // ......
    return peek(ptr, std::forward<Args>(args)...);
    }
    fgwmlhdkkkw
        6
    fgwmlhdkkkw  
    OP
       2022-04-14 17:44:58 +08:00
    @cnbatch #5 额,左值右值,值晕了~
    whitehack
        7
    whitehack  
       2022-04-14 17:47:40 +08:00
    感觉已经完全不会 c++了.

    这 [[nodiscard]] 是啥语法.. 还是两个 中括
    fgwmlhdkkkw
        8
    fgwmlhdkkkw  
    OP
       2022-04-14 17:49:37 +08:00
    @whitehack #7 ……Clion 教我加的
    fgwmlhdkkkw
        9
    fgwmlhdkkkw  
    OP
       2022-04-14 17:50:41 +08:00
    @whitehack #7 意思是,调用者不能忽略这个函数的返回值。
    cnbatch
        10
    cnbatch  
       2022-04-14 18:03:19 +08:00   1
    @whitehack [[nodiscard]]的意思楼上已经说了,那我就稍作补充。

    这是 C++17 新属性
    en.cppreference.com/w/cpp/language/attributes/nodiscard

    很快就连 C 语言也能用上这个属性( C23 )
    en.cppreference.com/w/c/language/attributes/nodiscard
    cnbatch
        11
    cnbatch  
       2022-04-14 18:38:31 +08:00
    @fgwmlhdkkkw 忘了补一个 T key 的万能引用

    const Value * peek(const Value * src, T key, Args && ... args)

    可以适当改成

    const Value * peek(const Value * src, T && key, Args && ... args)
    {
    auto ptr = peek(src, std::forward(key));
    if (ptr == nullptr) return nullptr;
    return peek(ptr, std::forward<Args>(args)...);
    }

    至于应不应该改,那就视乎你的具体需要而定
    lonewolfakela
        12
    lonewolfakela  
       2022-04-14 22:53:24 +08:00
    @fgwmlhdkkkw #4 我不太明白你的“不想复制”指的是啥。就我看来你这里用一个 std::vector<std::variant<std::string,int>>就能满足需求了的样子?
    fgwmlhdkkkw
        13
    fgwmlhdkkkw  
    OP
       2022-04-15 09:48:21 +08:00
    @lonewolfakela #12 你不说我都不知道,c++也有 union……谢谢
    fgwmlhdkkkw
        14
    fgwmlhdkkkw  
    OP
       2022-04-15 09:53:05 +08:00
    @lonewolfakela #12 那其实所有的变长参数都可以写成这种 vector ,应该要比模板展开好吧?
    lonewolfakela
        15
    lonewolfakela  
       2022-04-15 10:19:40 +08:00
    @fgwmlhdkkkw #14 仅就你这个应用场景,我觉得 vector 更好。但是也有一些其他场景下更适合用模板,不然函数用起来会很难看(参考 https://en.cppreference.com/w/cpp/utility/format/formatter#Standard_format_specification ,这种 format 函数如果参数也用 vector 来传的话用起来肯定特别难受)。
    不过总的一般原则是优先考虑代码写起来美观、顺手,而不是优先考虑编译器会不会内联、编译出来的代码快不快之类问题;性能问题一般不要过早优化,代码写出来了如果确定有性能瓶颈的话再针对性优化。
    fgwmlhdkkkw
        16
    fgwmlhdkkkw  
    OP
       2022-04-15 10:28:28 +08:00
    @lonewolfakela #12 variant 和 optinal 一样,只能保存值,不能保存引用。那所有的字符串不都会 copy 一下吗?
    fgwmlhdkkkw
        17
    fgwmlhdkkkw  
    OP
       2022-04-15 10:49:38 +08:00
    @fgwmlhdkkkw #16 我可以用`const char*`,可以了,只是多写一组大括号,完美。
    lonewolfakela
        18
    lonewolfakela  
       2022-04-15 18:05:06 +08:00
    @fgwmlhdkkkw #16 如果你是想保存引用的话,那你需要 std::vector<std::variant<std::reference_wrapper<std::string>,int>>
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1445 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 16:46 PVG 00:46 LAX 08:46 JFK 11:46
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86