C++ 17 写法上已经很接近 python 了 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
taowen
V2EX    Python

C++ 17 写法上已经很接近 python 了

  •  4
     
  •   taowen 2016-08-27 20:35:25 +08:00 38049 次点击
    这是一个创建于 3334 天前的主题,其中的信息可能已经有所发展或是发生改变。

    list 和 map

    本节例子选自: https://gist.github.com/JeffPaine/6213790

    对 python 这样的动态语言最直观的感受就是 list/map 两种数据结构打天下。 php 和 lua 甚至把这两个都合并成一种数据结构了。 毋庸置疑,学会如何使用 list 和 map 是基础中的基础。

    for 循环

    Python 版本

    import unittest class Test(unittest.TestCase): def test_foreach_on_lazy_range(self): for i in xrange(6): print i ** 2 

    C++ 版本

    #include <catch_with_main.hpp> #include <range/v3/all.hpp> using namespace ranges; TEST_CASE("foreach on lazy range") { for(const auto& x : view::ints(0, 6)) { std::cout << x * x << std::endl; } } 

    注意到 const auto& 的写法,这个表示我对这个变量进行只读的使用。只要是能用 const 的地方就用 const ( http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#a-namerconst-immutableacon1-by-default-make-objects-immutable )。 为什么还需要加上 reference ?因为非 reference 的版本默认的语义我要拥有这个变量( make a copy )。而在 for 循环下我们显然是只打算使用这个变量, 而不是去拥有一份。为什么不用指针而用引用?因为指针可空, reference 不可空。

    view::ints 是 range-v3 这个库提供的,作用等同于 xrange 。将来 range-v3 会成为标准库的一部分。

    foreach

    Python 版本

    import unittest class Test(unittest.TestCase): def test_foreach_on_list(self): colors = ['red', 'green', 'blue', 'yellow'] for color in colors: print color 

    C++ 版本

    #include <catch_with_main.hpp> using namespace ranges; TEST_CASE("foreach on list") { auto colors = {"red", "green", "blue", "yellow"}; for(const auto& color : colors) { std::cout << color << std::endl; } } 

    与 python 不同, c++没有所谓的默认的 list 类型。上面的写法是最简洁的写法。 colors 变量的实际类型 根据 GDB 是 std::initializer_list<const char*>。只有 begin , end , size 几个函数。实际上类似于 python 的 tuple 。 考虑到 python 的 list 类型是 mutable 的,所以更合适的实现是 std::vector 。

    #include <catch_with_main.hpp> using namespace ranges; TEST_CASE("foreach on vector") { auto colors = std::vector<const char*>{"red", "green", "blue", "yellow"}; for(const auto& color : colors) { std::cout << color << std::endl; } } 

    foreach 倒序

    Python 版本

    import unittest class Test(unittest.TestCase): def test_foreach_reversed(self): colors = ['red', 'green', 'blue', 'yellow'] for color in reversed(colors): print(color) 

    C++ 版本

    #include <catch_with_main.hpp> #include <range/v3/all.hpp> using namespace ranges; TEST_CASE("foreach reversed") { auto colors = std::vector<const char*>{"red", "green", "blue", "yellow"}; for(const auto& color : colors | view::reverse) { std::cout << color << std::endl; } } 

    这里使用了 range-v3 的 view 组合,类似 unix pipe 的语法。

    foreach 带下标

    Python 版本

    import unittest class Test(unittest.TestCase): def test_foreach_with_index(self): colors = ['red', 'green', 'blue', 'yellow'] for i, color in enumerate(colors): print(i, color) 

    C++ 版本

    #include <catch_with_main.hpp> #include <range/v3/all.hpp> using namespace ranges; TEST_CASE("foreach with index") { auto colors = std::vector<const char*>{"red", "green", "blue", "yellow"}; for(const auto& [i, color] : view::zip(view::iota(0), colors)) { std::cout << i << " " << color << std::endl; } } 

    view::iota这个的意思是产生一个从 n 开始的逐个加一的 view ,类似 python 里的 generator 。然后 zip 是把两个 view 逐个对应起来合并成一个 pair 的 view 。 然后const auto& [i, color]是 c++ 17 的 structured bindings 的写法,和 python 解开 tuple 里的元素的做法是如出一辙的。

    zip

    下面这个例子可以看得更清楚。 Python 版本

    import unittest import itertools class Test(unittest.TestCase): def test_zip(self): names = ['raymond', 'rachel', 'matthew'] colors = ['red', 'green', 'blue', 'yellow'] for name, color in itertools.izip(names, colors): print(name, color) 

    izip 返回的是 generator 。 zip 返回都是 list 。 C++ 版本

    #include <catch_with_main.hpp> #include <range/v3/all.hpp> using namespace ranges; TEST_CASE("zip") { auto names= std::vector<const char*>{"raymond", "rachel", "matthew"}; auto colors = std::vector<const char*>{"red", "green", "blue", "yellow"}; for(const auto& [name, color] : view::zip(names, colors)) { std::cout << name << " " << color << std::endl; } } 

    sorted

    Python 版本

    import unittest class Test(unittest.TestCase): def test_sort(self): colors = ['red', 'green', 'blue', 'yellow'] for color in sorted(colors): print(color) 

    C++ 版本

    #include <catch_with_main.hpp> #include <range/v3/all.hpp> using namespace ranges; TEST_CASE("sort") { auto colors = std::vector<std::string>{"red", "green", "blue", "yellow"}; colors |= action::sort; for(const auto& color : colors) { std::cout << color << std::endl; } } 

    这个例子里const char*换成了std::string,因为只有字符串类型才知道怎么比较,才能排序。 action::sort与 view 不同,它返回的是具体的 container ,而不再是 view 了。

    如果要倒过来排序,再 python 中是这样的

    import unittest class Test(unittest.TestCase): def test_sort_reverse(self): colors = ['red', 'green', 'blue', 'yellow'] for color in sorted(colors, reverse=True): print(color) 

    C++ 版本

    #include <catch_with_main.hpp> #include <range/v3/all.hpp> using namespace ranges; TEST_CASE("sort reverse") { auto colors = std::vector<std::string>{"red", "green", "blue", "yellow"}; colors |= action::sort(std::greater<std::string>()); for(const auto& color : colors) { std::cout << color << std::endl; } } 

    Python 还支持指定属性去排序

    import unittest class Test(unittest.TestCase): def test_custom_sort(self): colors = ['red', 'green', 'blue', 'yellow'] for color in sorted(colors, key=lambda e: len(e)): print(color) 

    C++ 版本

    #include <catch_with_main.hpp> #include <range/v3/all.hpp> using namespace ranges; TEST_CASE("custom sort") { auto colors = std::vector<std::string>{"red", "green", "blue", "yellow"}; colors |= action::sort(std::less<std::string>(), [](const auto&e) { return e.size(); }); for(const auto& color : colors) { std::cout << color << std::endl; } } 

    sort的第一个参数是 comparator ,第二个参数是 projector 。这里我们使用了一个 lambda 表达式,从字符串上取得其长度值,用长度去排序。


    需要的编译环境

    • 操作系统: ubuntu 14.04
    • 编译器 clang 4.0: http://apt.llvm.org/ 使用 c++ 17
    • cmake: sudo apt-get install cmake
    • 包管理: git clone 依赖到自己的 repository ,所谓 vendoring
    • IDE clion : https://www.jetbrains.com/clion/
    • STL: libc++ 3.9
    • range-v3

    参见: https://taowen.gitbooks.io/modern-cpp-howto/content/unit-testing/chapter.html

    第 1 条附言    2016-08-28 09:03:53 +08:00
    77 条回复    2016-08-31 12:18:19 +08:00
    kindjeff
        1
    kindjeff  
       2016-08-27 20:38:41 +08:00   11
    仿佛自己没有学过 C++…………
    taowen
        2
    taowen  
    OP
       2016-08-27 20:40:25 +08:00
    @kindjeff 2000 年的时候学的 c++,十六年之后重新再学一门新语言,只是名字还是叫 c++。有了 lambda , auto , structured bindings 之后, c++已经是一门适合制造语法糖的语言了。
    yangff
        3
    yangff  
       2016-08-27 20:40:34 +08:00
    第一个 Case 如果都是 int 的话…… 直接用 int 比较合算……
    hinkal
        4
    hinkal  
       2016-08-27 20:55:13 +08:00
    你们都在模仿 python 系列,《 java8 写法上已经很接近 python 了》
    int64ago
        5
    int64ago  
       2016-08-27 20:57:51 +08:00
    所以的你发的节点是 Python ...

    几年没看 C++ 发现已经不认识了
    qweweretrt515
        6
    qweweretrt515  
       2016-08-27 21:07:17 +08:00
    啊哈 放佛学过 c++
    alexapollo
        7
    alexapollo  
       2016-08-27 21:25:30 +08:00
    之前写过一个 C++ Python 化的库,语法比这个更简洁,但介入的点比较少。
    janxin
        8
    janxin  
       2016-08-27 21:26:09 +08:00
    我们来谈谈内存管理吧
    shijingshijing
        9
    shijingshijing  
       2016-08-27 21:29:49 +08:00
    强迫症表示只喜欢 C++这种括号反括号的代码方式~
    sc3263
        10
    sc3263  
       2016-08-27 21:33:39 +08:00
    @janxin 智能指针大法好~
    k9982874
        11
    k9982874  
       2016-08-27 21:35:37 +08:00 via iPad   1
    auto 这种语法糖真是蛋疼。不敢想象一个大型项目全是 auto 该多么欢乐。
    neosfung
        12
    neosfung  
       2016-08-27 21:36:54 +08:00
    我现在还只停留在 c++ 0x 上面。。。
    zhuangzhuang1988
        13
    zhuangzhuang1988  
       2016-08-27 21:36:57 +08:00
    我那个擦。。
    hitmanx
        14
    hitmanx  
       2016-08-27 21:48:13 +08:00
    有些还能忍忍,比如 range-based for loop,可能也是习惯 c++11 了。
    但是这种 pipeline style 看着实在太怪异了:
    1) for(const auto& color : colors | view::reverse)
    2) colors |= action::sort;

    本来很简单很纯粹的“或”,现在看来也得分情况去理解了,很讨厌这种二义性
    missdeer
        15
    missdeer  
       2016-08-27 21:50:33 +08:00
    大部分在 C++11 都实现了,那是 5 年前的东西了
    missdeer
        16
    missdeer  
       2016-08-27 21:53:17 +08:00
    @hitmanx 早年的各种 C++ practice 里都说过,不要乱用操作符重载,特别是重载出跟惯用含义不同的行为来,叹气
    misaka19000
        17
    misaka19000  
       2016-08-27 21:56:12 +08:00
    Python 这种算不算模仿 Lisp 呢?

    《黑客与画家》里面就说过,现代的各种编程语言都是在慢慢的模仿 Lisp 的写法,并且这种趋势还在慢慢的增强,一种语言模仿 Lisp 的部分越多就越强大
    regeditms
        18
    regeditms  
       2016-08-27 22:08:28 +08:00
    c++17 现在什么编译器才支持哈? vs2015 ?
    kingoldlucky
        19
    kingoldlucky  
       2016-08-27 22:08:57 +08:00
    算了 还是看看纯 C 就好了
    billlee
        20
    billlee  
       2016-08-27 22:10:16 +08:00
    int 类型还用常量引用不是蛋疼吗。。
    skydiver
        21
    skydiver  
       2016-08-27 22:10:36 +08:00 via iPad
    应该用右值引用吧 auto&&
    zhenyan
        22
    zhenyan  
       2016-08-27 22:11:59 +08:00
    @regeditms VS2020 还差不多
    jyf007
        23
    jyf007  
       2016-08-27 22:13:35 +08:00 via Android
    向着 lisp 和 smalltalk 前进
    taowen
        24
    taowen  
    OP
       2016-08-27 22:15:33 +08:00
    @regeditms clang++ 4.0 应该是目前唯一支持 structured bindings 的编译器
    wodesuck
        25
    wodesuck  
       2016-08-27 22:22:46 +08:00   1
    可以 这代码很骚
    不过主要骚的地方都是 range-v3 吧, c++17 的特性似乎就只有 auto [x, y] = xxxx 了
    htfy96
        26
    htfy96  
       2016-08-27 22:41:24 +08:00
    @billlee
    @yangff 开个 O2 gcc 下完全一样……
    ninjadq
        27
    ninjadq  
       2016-08-27 22:44:47 +08:00
    仿佛学过 C++ +1 = =
    tracymcladdy
        28
    tracymcladdy  
       2016-08-27 22:57:01 +08:00 via Android
    还是 c 纯粹
    regeditms
        29
    regeditms  
       2016-08-27 23:02:59 +08:00
    @taowen 哦, 看来 mac 上也要用 brew 安装 clang 最新版本了。
    bjrjk
        30
    bjrjk  
       2016-08-27 23:04:48 +08:00
    你确定这个是 C++?
    lzhCoooder
        31
    lzhCoooder  
       2016-08-27 23:32:47 +08:00
    带着手动管理内存的包袱,却有这么高级的语法真的合适吗?
    真的彻底和 ANSI C 分道扬镳了
    lsmgeb89
        32
    lsmgeb89  
       2016-08-27 23:41:09 +08:00
    现在除了 cppcon 哪里还能看点 C++17 的东西?
    yangff
        33
    yangff  
       2016-08-27 23:54:54 +08:00
    @k9982874 还好, C++的 auto 都能推倒类型
    taowen
        34
    taowen  
    OP
       2016-08-27 23:56:55 +08:00   1
    yuankui
        35
    yuankui  
       2016-08-28 09:21:49 +08:00   1
    这语法,丑的一笔。。
    Em5O7B1JGfjQnBry
        36
    Em5O7B1JGfjQnBry  
       2016-08-28 09:34:58 +08:00 via Android   1
    感觉适应一下新标准花不了多少时间,还可以学到很多东西,可现在也很多人还是用 C+class 操着 C++,很多人声称 STL 就是个垃圾(;)
    sinopec
        37
    sinopec  
       2016-08-28 09:50:05 +08:00
    c++坑太深,奇技淫巧跟新东西太多,学无止境啊,而且学的大部分还都用不到,好处是,现在学啥语言都不太费力....
    linux40
        38
    linux40  
       2016-08-28 09:55:27 +08:00 via Android
    c++17 标准库还是加了很多东西嘛。。。
    htfy96
        39
    htfy96  
       2016-08-28 09:56:28 +08:00 via Android   1
    感觉国内的风向就是
    1 纯 C 好 简洁
    2 学了 C 自然就懂 C++了
    3 新标准有什么用,一堆公司还在用 C++98
    4 C++=C + STL 或者退化成 C with class
    5 C++异常不管什么时候都差劲 还是 errCode 靠谱

    虽然是因为国内一些客观因素决定的(比如说教学、招人成本之类的),但是这样下去只能会搞成国内特色的东西
    linux40
        40
    linux40  
       2016-08-28 09:58:31 +08:00 via Android
    至少动态语言是在模仿 lisp 。。。
    gimp
        41
    gimp  
       2016-08-28 10:00:07 +08:00
    看 ES6 ,我还以为 python 开发者打入他们的标准委员会内部了呢
    mind3x
        42
    mind3x  
       2016-08-28 11:20:48 +08:00 via Android
    @hitmanx 这个地方根据上下文看其实还好
    bobylive
        43
    bobylive  
       2016-08-28 11:57:06 +08:00 via Android
    C 艹的坑这是一年比一年深了
    relcodego
        44
    relcodego  
       2016-08-28 12:57:20 +08:00 via Android
    已经回不去 c++了。。。
    kingddc314
        45
    kingddc314  
       2016-08-28 14:25:36 +08:00
    这几乎都是 C++11 的东西, C 风格写 C++的就不要大惊小怪了
    bombless
        46
    bombless  
       2016-08-28 15:37:24 +08:00 via Android
    cpp 比较尴尬的还是 split ……基本只能到处拷贝
    palxex
        47
    palxex  
       2016-08-28 16:01:21 +08:00
    这只是看起来像而已。用 C++写一个字面量 json 试试?不用复杂,{"int":1,"string":"test"}就行。
    用 python 写东西时感受的随心所欲,很大一个方面来自于它的动态类型不受 expression problem 影响,这是它受 lisp 影响最核心的部分,而不是流于表面的 map/reduce/filter 支持。这个问题是 C++过去,现在以及看得到的将来都不可能解决的。
    taowen
        48
    taowen  
    OP
       2016-08-28 16:25:59 +08:00
    @palxex
    ```
    #include <catch_with_main.hpp>
    #include <json.hpp>

    using json = nlohmann::json;

    TEST_CASE("json literal") {
    json obj {
    {"int", 1},
    {"string", "test"},
    };
    std::cout << obj << std::endl;
    }
    ```

    https://github.com/nlohmann/json
    palxex
        49
    palxex  
       2016-08-28 16:44:09 +08:00
    @taowen 还真有啊!多谢,我看看这个库。以前此类库最大的问题是极难与 STL 协作,因为 json 的本质要求此类库必须自己搞出自己的单根体系当 any 。
    secondwtq
        50
    secondwtq  
       2016-08-28 18:39:40 +08:00
    涨姿势了

    不过我还是喜欢“ C++ 特色”,像不像 Python 对我来说并没有什么所谓
    soland
        51
    soland  
       2016-08-28 19:20:26 +08:00   1
    语法糖衣,里面还是炮弹。
    SuperFashi
        52
    SuperFashi  
       2016-08-28 19:43:02 +08:00
    真的就是语法糖而已。让我比较惊奇的是 C++17 里自带 gcd 和 lcm ,不过这是基本功。
    不管怎么样,目前 NOI/P 只能用 C++98 ,所以这些对我来说没什么用。
    什么,你说不打竞赛的时候用?不大竞赛用个 P 的 C++,放着大好的 Python 和 Go 不用。
    SuperFashi
        53
    SuperFashi  
       2016-08-28 19:49:40 +08:00
    不过吐槽一句, python 实例代码不是很 pythonic ,例如排序那个写成 sorted(colors, key=len) 就好。
    xuboying
        54
    xuboying  
       2016-08-28 20:00:37 +08:00 via Android
    taowen/td>
        55
    taowen  
    OP
       2016-08-28 20:41:40 +08:00
    @SuperFashi 故意写成 lambda 让对比更明显的。这不是比赛,只是让 python 程序员快速找到 c++里的对等概念。
    htfy96
        56
    htfy96  
       2016-08-28 21:52:23 +08:00
    @SuperFashi Golang 还是算了吧。。天天写的要吐了……。语法太简洁导致要用自定义功能的时候会很繁琐……来试试写一个自定义 key 的 sort 就知道了……
    mozartgho
        57
    mozartgho  
       2016-08-28 22:55:25 +08:00
    C++的写法比起 Python 仍然不够简洁,感觉委员会的那帮人把 C++搞得越来越复杂了,各种新的语法糖。编译器严重落后标准。
    wshcdr
        58
    wshcdr  
       2016-08-28 23:04:13 +08:00
    C++努力地向动态语言靠近,不过,个人不看好
    taowen
        59
    taowen  
    OP
       2016-08-28 23:46:41 +08:00
    @mozartgho http://en.cppreference.com/w/cpp/compiler_support 目测还好。编译器严重落后标准这个说法是不是来自于 template export 这个特性?
    srlp
        60
    srlp  
       2016-08-29 01:47:06 +08:00 via iPhone   1
    @palxex json 也可以用 folly::dynamic ,会尽量 cast 到原生类型。
    jeffersonpig
        61
    jeffersonpig  
       2016-08-29 08:46:57 +08:00
    好吧原来我一直是个 C++门外汉
    gougudingli
        62
    gougudingli  
       2016-08-29 08:57:12 +08:00
    有些编程书,还在让读者装 VC++6.o 。心生疑惑: C++11 、 17 那么多版本,究竟是哪些人来维护和修改的?
    stormpeach
        63
    stormpeach  
       2016-08-29 09:03:57 +08:00
    @hitmanx 不能更同意,所以现在去学 rust 了。。。
    stormpeach
        64
    stormpeach  
       2016-08-29 09:08:08 +08:00
    看来又要出一本新的书了:《 effective range-v3 》。。。
    lcc4376
        65
    lcc4376  
       2016-08-29 09:11:49 +08:00
    上次 c++是 08 年的事
    gotham
        66
    gotham  
       2016-08-29 09:16:55 +08:00
    你是 sb 吗, TEST_CASE 这种写法出现十多年了。
    joye1230
        67
    joye1230  
       2016-08-29 09:31:25 +08:00
    re 从零开始 c++
    likebeta
        68
    likebeta  
       2016-08-29 09:37:48 +08:00
    @gotham 楼主再说 TEST_CASE ? 智商是硬伤
    hei1000
        69
    hei1000  
       2016-08-29 09:43:30 +08:00
    搞得这么复杂,还是喜欢 C,尽管有缺陷,但也没看像 C++这样什么都往里面家
    wubotao
        70
    wubotao  
       2016-08-29 09:58:51 +08:00
    好久不写 C++ 了。
    bp0
        71
    bp0  
       2016-08-29 10:14:38 +08:00
    算了,我已经不认识 C++了,还是默默的写 C 吧。
    cppgohan
        72
    cppgohan  
       2016-08-29 10:25:02 +08:00
    不说语言之争, 语言工具各有利弊. :)

    view 是默认的命名空间吗? 略微有点奇怪.

    好久没在生产环境写 C++, 从没在生产环境写过 C++11, 不知道这里哪些地方用了 C++17 的哪些特性? 楼主可以多分享分享, 还是挺有兴趣的.


    至于 python, 主要是写起来简单, 不用考虑如同 c++那种更复杂完备的 lambda 语法, 常量引用这些.

    比如你的例子中的排序, python 一行列表析取式就直接搞定了.
    print [x for x in sorted(['red', 'green', 'blue', 'yellow'])]


    这两年工作以做 android 开发 /java 语言为主, 过去的 c++底子有点秀逗了. python 也是更早自学敲敲打打的.

    但是 python 捡起来相比 c++还是容易太多了.

    C++对人的要求更高些, 暴露的更多细节, 如果经验攒的不够, 更容易写出更坏味道的代码.

    就如同 steve yegge 说 java 语言: Java 语言有个优点, 它让那些烂程序员造不成太大的破坏性:).
    taowen
        73
    taowen  
    OP
       2016-08-29 10:31:11 +08:00
    @cppgohan 所以需要更多 http://clang.llvm.org/extra/clang-tidy/ 和 clion 这样的 IDE ,把经验变成静态检查。新的 GSL 规范利用静态检查来做所有权和边界安全。基本上相当于是利用静态检查在 c++的基础上发明一个子集的语言的感觉了。这门新的语言虽然还叫 c++,但是就不那么需要依赖程序员自律来保障安全了。
    wizardforcel
        74
    wizardforcel  
       2016-08-29 10:46:31 +08:00
    我之前把一个 node 写的代码用 c++11 翻写了一遍,发现除了不支持字典的字面值,其它还好。
    wangkun2012324
        75
    wangkun2012324  
       2016-08-29 16:31:02 +08:00
    这样看来, Swift 还是不错的,哈哈哈
    andypinet
        76
    andypinet  
       2016-08-30 13:04:36 +08:00
    c++ 23 估计可以更 python
    lellansin
        77
    lellansin  
       2016-08-31 12:18:19 +08:00
    可啪
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     916 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 21:19 PVG 05:19 LAX 14:19 JFK 17:19
    Do have faith in what you're doing.
    ubao 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