├── .gitignore ├── README.md ├── base ├── Dockerfile ├── boost.sh └── setup.sh ├── cert └── selfsign.sh ├── ch1 └── test.cpp ├── ch2 ├── attribute.cpp ├── codestyle.cpp ├── fab.cpp ├── preprocess.cpp └── static_assert.cpp ├── ch3 ├── auto.cpp ├── const.cpp ├── constexpr.cpp ├── exception.cpp ├── lambda.cpp ├── oop.cpp └── others.cpp ├── ch4 ├── algo.cpp ├── any.cpp ├── async.cpp ├── atomic.cpp ├── call_once.cpp ├── container.cpp ├── filesystem.cpp ├── fmt.cpp ├── for_each.cpp ├── optional.cpp ├── par_algo.cpp ├── ranges.cpp ├── regex.cpp ├── search.cpp ├── shared_ptr.cpp ├── sort.cpp ├── string.cpp ├── string_view.cpp ├── thread.cpp ├── thread_local.cpp ├── tuple.cpp ├── unique_ptr.cpp ├── variant.cpp └── weak_ptr.cpp ├── ch5 ├── a.com.crt ├── a.com.key ├── cinatra.cpp ├── cpr.cpp ├── curl.cpp ├── demo.py ├── embedded.lua ├── flame.svg ├── gperf.cpp ├── icicle.svg ├── json.cpp ├── lexical_cast.cpp ├── lua_shared.cpp ├── luajit.cpp ├── msgpack.cpp ├── protobuf.cpp ├── ptree.cpp ├── pybind.cpp ├── sample.proto ├── sample.proto.v2 ├── sample.proto.v3 ├── shared.lua ├── string_algo.cpp ├── timer.cpp └── zmq.cpp ├── ch7 ├── Config.hpp ├── SalesData.hpp ├── SpinLock.hpp ├── Summary.hpp ├── Zmq.hpp ├── backend.cpp ├── cli.cpp ├── conf.lua ├── cpplang.hpp └── srv.cpp ├── common └── std.hpp ├── docker ├── Dockerfile ├── docker-compose.yml └── setup.sh ├── env ├── bashrc ├── gitconfig └── vimrc ├── k8s └── cpp-note-pod.yml └── run.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # own config 35 | a.out 36 | *.swp 37 | *.pb.* 38 | example_*_cpp* 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cpp_note 2 | C++ practice notebook 3 | 4 | ## Requirements 5 | 6 | * Linux : Ubuntu, Debian, CentOS, and others 7 | * macOS(OS X) : may work but not be tested 8 | 9 | ## Docker 10 | 11 | You can also use this in docker, it bases on gcc7/10: 12 | 13 | ```docker 14 | docker pull chronolaw/cpp_note 15 | docker run -it --rm chronolaw/cpp_note 16 | ``` 17 | 18 | ## Reference 19 | 20 | * [ISO C++](http://www.open-std.org/jtc1/sc22/wg21/) 21 | * [Standard C++ Foundation](https://isocpp.org/) 22 | * [cppreference(en)](https://en.cppreference.com/w/) 23 | * [cppreference(zh)](https://zh.cppreference.com/w/) 24 | 25 | 26 | ## Resource 27 | 28 | * [VirtualBox](https://www.virtualbox.org) 29 | * [Ubuntu](https://ubuntu.com/) 30 | * [GCC](http://gcc.gnu.org/) 31 | * [Clang](http://clang.llvm.org/) 32 | 33 | 34 | ## Document 35 | 36 | * [Bjarne Stroustrup's FAQ](http://www.stroustrup.com/bs_faq.html) 37 | * [Bjarne Stroustrup's C++11 FAQ](http://www.stroustrup.com/C++11FAQ.html) 38 | * [Bjarne Stroustrup's C++ HOPL4(zh-cn)](https://github.com/Cpp-Club/Cxx_HOPL4_zh) 39 | * [C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) 40 | * [OpenResty Code Style Guide(zh-cn)](http://openresty.org/cn/c-coding-style-guide.html) 41 | * [Google Code Style Guide](https://google.github.io/styleguide/cppguide.html) 42 | * [ProtoBuffer C++ Doc](https://developers.google.com/protocol-buffers/docs/reference/cpp-generated) 43 | 44 | 45 | ## Dev Links 46 | 47 | * [PCRE](http://www.pcre.org/) 48 | * [Boost](https://www.boost.org/) 49 | * [tbb](https://github.com/intel/tbb) 50 | * [JSON](https://www.json.org/json-zh.html) 51 | * [JSON for Modern C++](https://github.com/nlohmann/json) 52 | * [MessagePack](https://msgpack.org/) 53 | * [msgpack-c](https://github.com/msgpack/msgpack-c) 54 | * [ProtoBuf](https://github.com/protocolbuffers/protobuf) 55 | * [protobuf-c](https://github.com/protobuf-c/protobuf-c) 56 | * [gRPC](https://grpc.io) 57 | * [Thrift](https://thrift.apache.org/) 58 | * [libcurl](https://curl.haxx.se/libcurl/) 59 | * [cpr](https://github.com/whoshuu/cpr) 60 | * [cinatra](https://github.com/qicosmos/cinatra) 61 | * [ZMQ](https://zeromq.org/) 62 | * [cppzmq](https://github.com/zeromq/cppzmq) 63 | * [pybind11](https://github.com/pybind/pybind11) 64 | * [lua](https://www.lua.org/) 65 | * [luajit](http://luajit.org/) 66 | * [luajit-openresty](https://github.com/openresty/luajit2) 67 | * [LuaBridge](https://github.com/vinniefalco/LuaBridge) 68 | * [gperftools](https://github.com/gperftools/gperftools) 69 | * [FlameGraph](https://github.com/brendangregg/FlameGraph) 70 | * [OpenResty XRay](https://openresty.com.cn/cn/xray/) 71 | 72 | ## Awesome collection 73 | 74 | * [Awesome C++](https://github.com/fffaraz/awesome-cpp) 75 | * [Awesome Mordern C++](https://github.com/rigtorp/awesome-modern-cpp) 76 | 77 | ## See Also 78 | 79 | * [C++实战笔记](https://time.geekbang.org/column/intro/309) 80 | * [透视HTTP协议](https://time.geekbang.org/column/intro/189) 81 | * [http_study](https://github.com/chronolaw/http_study) - http service for pratice and more 82 | * [boost guide](https://github.com/chronolaw/boost_guide.git) - Sample code for Boost library Guide 83 | * [professional_boost](https://github.com/chronolaw/professional_boost.git) - Professional boost development 84 | * [annotated_nginx](https://github.com/chronolaw/annotated_nginx) - 注释nginx,学习研究源码 85 | * [ngx_cpp_dev](https://github.com/chronolaw/ngx_cpp_dev) - Nginx C++ development kit, with the power of C++11 and Boost Library 86 | * [ngx_ansic_dev](https://github.com/chronolaw/ngx_ansic_dev) - Nginx ANSI C Development 87 | * [openresty_dev](https://github.com/chronolaw/openresty_dev) - OpenResty/Lua Programming 88 | * [favorite-nginx](https://github.com/chronolaw/favorite-nginx) - Selected favorite nginx modules and resources 89 | -------------------------------------------------------------------------------- /base/Dockerfile: -------------------------------------------------------------------------------- 1 | # Dockerfile 2 | # chrono@2021-03 3 | 4 | # curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun 5 | # sudo service docker start 6 | # sudo usermod -aG docker ${USER} 7 | 8 | # docker build -t chronolaw/cpp_note . 9 | # SRC_IMAGE=gcc:7 docker build -f Dockerfile -t chronolaw/cpp_base:gcc7 . 10 | # SRC_IMAGE=gcc:10 docker build -f Dockerfile -t chronolaw/cpp_base:gcc10 . 11 | 12 | # docker run -it --rm chronolaw/cpp_note 13 | 14 | ARG SRC_IMAGE="gcc:7" 15 | #ARG SRC_IMAGE="gcc:10" 16 | 17 | FROM ${SRC_IMAGE} 18 | 19 | WORKDIR /root 20 | 21 | #RUN DEBIAN_FRONTEND=noninteractive apt-get update \ 22 | # && DEBIAN_FRONTEND=noninteractive apt-get install -y \ 23 | # vim cmake gdb pstack strace \ 24 | # libmsgpack-dev protobuf-compiler libprotobuf-dev libprotoc-dev \ 25 | # libcurl4-openssl-dev libzmq3-dev \ 26 | # python3-dev python3-pip \ 27 | # google-perftools libgoogle-perftools-dev \ 28 | # && pip3 install pybind11 \ 29 | # && DEBIAN_FRONTEND=noninteractive apt-get autoremove -y 30 | 31 | COPY setup.sh /tmp 32 | 33 | RUN /tmp/setup.sh 34 | 35 | CMD ["/bin/bash"] 36 | -------------------------------------------------------------------------------- /base/boost.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VER_DOT='1.75.0' 4 | VER_DASH='1_75_0' 5 | 6 | #wget https://dl.bintray.com/boostorg/release/${VER_DOT}/source/boost_${VER_DASH}.tar.gz 7 | 8 | tar xfz boost_${VER_DASH}.tar.gz 9 | cd boost_${VER_DASH} 10 | 11 | 12 | ./bootstrap.sh 13 | ./b2 tools/bcp 14 | 15 | ./dist/bin/bcp lexical_cast .. 16 | ./dist/bin/bcp string_algo .. 17 | ./dist/bin/bcp property_tree .. 18 | -------------------------------------------------------------------------------- /base/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # chrono @ 2021-04 4 | 5 | # apt-get 6 | # libboost-dev libboost-all-dev 7 | DEBIAN_FRONTEND=noninteractive apt-get update 8 | DEBIAN_FRONTEND=noninteractive apt-get install -y \ 9 | vim cmake gdb pstack strace \ 10 | libboost-system-dev libboost-timer-dev \ 11 | libmsgpack-dev protobuf-compiler libprotobuf-dev libprotoc-dev \ 12 | libcurl4-openssl-dev libzmq3-dev \ 13 | python3-dev python3-pip \ 14 | google-perftools libgoogle-perftools-dev 15 | 16 | DEBIAN_FRONTEND=noninteractive apt-get autoremove -y 17 | 18 | # python3 pybind11 19 | pip3 install pybind11 20 | 21 | #WORKDIR='/root/' 22 | #HOME='/root' 23 | 24 | # source 25 | 26 | JSON_VERSION="3.9.1" 27 | SPDLOG_VERSION="1.8.5" 28 | CPR_VERSION="1.4.0" 29 | LUAJIT_VERSION="2.1-20201229" 30 | LUABRIDAGE_VERSION="2.6" 31 | GPERF_VERSION="2.9.1" 32 | 33 | #echo ${JSON_VERSION} 34 | #echo ${HOME} 35 | 36 | mkdir ~/github 37 | cd ~/github 38 | 39 | # test 40 | #exit 41 | 42 | # json 43 | curl -fsL https://github.com/nlohmann/json/releases/download/v${JSON_VERSION}/json.hpp -o json.hpp 44 | #ln -s ~/github/json.hpp ~/${REPO}/common/ 45 | 46 | # spdlog && fmtlib 47 | curl -fsL https://github.com/gabime/spdlog/archive/v${SPDLOG_VERSION}.tar.gz -o spdlog.tgz 48 | tar xfz spdlog.tgz 49 | cd spdlog-${SPDLOG_VERSION} 50 | mkdir build && cd build 51 | cmake .. && make -j && make install && make clean 52 | cd ../.. 53 | 54 | # curl/cpr 55 | curl -fsL https://github.com/whoshuu/cpr/archive/${CPR_VERSION}.tar.gz -o cpr.tgz 56 | tar xfz cpr.tgz 57 | cd cpr-${CPR_VERSION} 58 | cmake . -DUSE_SYSTEM_CURL=ON -DBUILD_CPR_TESTS=OFF 59 | make && make install && make clean 60 | cd .. 61 | 62 | # cinatra 63 | git clone https://github.com/qicosmos/cinatra --depth=1 64 | #git clone git@github.com:qicosmos/cinatra.git --depth=1 65 | #ln -s ~/github/cinatra/include/cinatra ~/${REPO}/common/cinatra 66 | #ln -s ~/github/cinatra/include/cinatra.hpp ~/${REPO}/common/ 67 | 68 | # luajit 69 | curl -fsL https://github.com/openresty/luajit2/archive/v${LUAJIT_VERSION}.tar.gz -o luajit.tgz 70 | tar xfz luajit.tgz 71 | cd luajit2-${LUAJIT_VERSION} 72 | make && make install && make clean 73 | ln -s /usr/local/lib/libluajit-5.1.so.2 /lib/x86_64-linux-gnu/ 74 | cd .. 75 | 76 | # luabridge 77 | curl -fsL https://github.com/vinniefalco/LuaBridge/archive/${LUABRIDAGE_VERSION}.tar.gz -o LuaBridge.tgz 78 | tar xfz LuaBridge.tgz 79 | #ln -s ~/github/LuaBridge-${LUABRIDAGE_VERSION}/Source/LuaBridge/ ~/${REPO}/common/ 80 | 81 | # gperftools 82 | curl -fsL https://github.com/gperftools/gperftools/releases/download/gperftools-${GPERF_VERSION}/gperftools-${GPERF_VERSION}.tar.gz -o gperf.tgz 83 | tar xfz gperf.tgz 84 | ln -s ~/github/gperftools-${GPERF_VERSION}/pprof-symbolize /bin/pprof 85 | 86 | # flame graph 87 | git clone https://github.com/brendangregg/FlameGraph.git --depth=1 88 | #git clone git@github.com:brendangregg/FlameGraph.git --depth=1 89 | ln -s ~/github/FlameGraph/flamegraph.pl /usr/local/bin/flamegraph.pl 90 | 91 | # clean 92 | rm *.tgz 93 | 94 | -------------------------------------------------------------------------------- /cert/selfsign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #ca="chrono.ca" 4 | 5 | if [ -z "$1" ]; then 6 | echo "needs domain name" 7 | exit 1 8 | fi 9 | 10 | domain=$1 11 | 12 | ca="${domain}" 13 | #ca="${domain}.ca" 14 | 15 | days=3650 16 | 17 | openssl req -x509 -days ${days} -out ${domain}.crt -keyout ${domain}.key \ 18 | -newkey rsa:2048 -nodes -sha256 \ 19 | -subj "/CN=${ca}" -extensions EXT -config <( \ 20 | printf "[dn]\nCN=${domain}\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:${domain}\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth") 21 | -------------------------------------------------------------------------------- /ch1/test.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ test.cpp -std=c++17 -o a.out;./a.out 4 | // g++ test.cpp -std=c++20 -o a.out;./a.out 5 | // g++ test.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | //#include "std.hpp" 10 | 11 | int main() 12 | { 13 | using namespace std; 14 | 15 | cout << "c++ version = " << __cplusplus << endl; 16 | 17 | cout << "gcc version = " << __VERSION__ << endl; 18 | 19 | cout << "gcc major = " << __GNUC__ << endl; 20 | cout << "gcc minor = " << __GNUC_MINOR__ << endl; 21 | cout << "gcc patch = " << __GNUC_PATCHLEVEL__ << endl; 22 | 23 | cout << "libstdc++ = " << __GLIBCXX__ << endl; 24 | } 25 | -------------------------------------------------------------------------------- /ch2/attribute.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 by Chrono 2 | // 3 | // g++ attribute.cpp -Werror -std=c++17 -o a.out;./a.out 4 | // g++ attribute.cpp -Werror -std=c++20 -o a.out;./a.out 5 | // g++ attribute.cpp -Wno-deprecated-declarations -std=c++17 -o a.out; 6 | // g++ attribute.cpp -Wno-deprecated-declarations -std=c++20 -o a.out; 7 | // 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | //[[gnu::deprecated]] // c+11 or later 18 | [[deprecated("deadline:2021-12-31")]] // c++14 or later 19 | int old_func() 20 | { 21 | //[[gnu::deprecated("I hate this")]] 22 | int value = 0; 23 | 24 | return value; 25 | } 26 | 27 | [[gnu::constructor]] 28 | void first_func() 29 | { 30 | // can not use cout! 31 | printf("before main()\n"); 32 | } 33 | 34 | [[gnu::destructor]] 35 | void last_func() 36 | { 37 | // can not use cout! 38 | printf("after main()\n"); 39 | } 40 | 41 | //[[gnu::const]] 42 | //[[gnu::always_inline]] inline 43 | [[using gnu : const, always_inline]] inline 44 | int get_num() 45 | { 46 | return 42; 47 | } 48 | 49 | [[noreturn]] 50 | int case1(bool flag) 51 | { 52 | throw std::runtime_error("XXX"); 53 | } 54 | 55 | void case2() 56 | { 57 | using namespace std; 58 | 59 | [[maybe_unused]] //[[gnu::unused]] 60 | int nouse; 61 | 62 | cout << "case2" << endl; 63 | } 64 | 65 | [[gnu::hot]] 66 | void case3() 67 | { 68 | using namespace std; 69 | 70 | cout << "case3" << endl; 71 | } 72 | 73 | int main() 74 | { 75 | using namespace std; 76 | 77 | old_func(); 78 | get_num(); 79 | 80 | case2(); 81 | case3(); 82 | 83 | cout << "attribute demo" << endl; 84 | } 85 | -------------------------------------------------------------------------------- /ch2/codestyle.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ codestyle.cpp -std=c++17 -o a.out;./a.out 4 | // g++ codestyle.cpp -std=c++20 -o a.out;./a.out 5 | // 6 | 7 | #include 8 | #include 9 | 10 | using std::string; 11 | 12 | #define MAX_PATH_LEN 256 13 | 14 | int g_sys_flag; 15 | 16 | namespace linux_sys { 17 | void get_rlimit_core(); 18 | } 19 | 20 | class FilePath final 21 | { 22 | public: 23 | void set_path(const string& str); 24 | private: 25 | string m_path; 26 | int m_level; 27 | }; 28 | 29 | 30 | // author : chrono 31 | // date : 2021-xx-xx 32 | // purpose : get inner counter value of generic T 33 | // notice : T must have xxx member 34 | // notice : return value maybe -1, means xxx, you should xxx 35 | template 36 | int get_value(const T& v); 37 | 38 | int main() 39 | { 40 | using namespace std; 41 | 42 | cout << "show your code style." << endl; 43 | } 44 | -------------------------------------------------------------------------------- /ch2/fab.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ fab.cpp -Wall -Werror -std=c++17 -o a.out;./a.out 4 | // g++ fab.cpp -Wall -Werror -std=c++20 -o a.out;./a.out 5 | // 6 | // gcc -E -dM - < /dev/null 7 | 8 | #include 9 | 10 | template 11 | struct fib 12 | { 13 | static_assert(N >= 0, "N must be postive"); 14 | 15 | static const int value = 16 | fib::value + fib::value; 17 | }; 18 | 19 | template<> 20 | struct fib<0> 21 | { 22 | static const int value = 1; 23 | }; 24 | 25 | template<> 26 | struct fib<1> 27 | { 28 | static const int value = 1; 29 | }; 30 | 31 | int main() 32 | { 33 | using namespace std; 34 | 35 | cout << fib<2>::value << endl; 36 | cout << fib<3>::value << endl; 37 | cout << fib<4>::value << endl; 38 | cout << fib<5>::value << endl; 39 | 40 | cout << "fab demo" << endl; 41 | } 42 | -------------------------------------------------------------------------------- /ch2/preprocess.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // pre-process source: 4 | // g++ preprocess.cpp -E -o a.cxx 5 | // 6 | // g++ preprocess.cpp -Wall -std=c++17 -o a.out;./a.out 7 | // g++ preprocess.cpp -Wall -std=c++20 -o a.out;./a.out 8 | // 9 | // g++ preprocess.cpp -DNDEBUG -std=c++17 -o a.out;./a.out 10 | // 11 | // show all predefined macro: 12 | // g++ -E -dM - < /dev/null 13 | // g++ -E -dM - < /dev/null > predef.cxx 14 | 15 | // comment it for better pre-process output 16 | #include 17 | 18 | #if __has_include() 19 | # include 20 | #endif 21 | 22 | using namespace std; 23 | 24 | // you can try this 25 | //#include "a.out" 26 | 27 | void case1() 28 | { 29 | # 30 | #if __linux__ 31 | # define HAS_LINUX 1 32 | #endif 33 | # 34 | cout << "linux is " << HAS_LINUX << endl; 35 | } 36 | 37 | void case2() 38 | { 39 | #define CUBE(a) (a) * (a) * (a) 40 | 41 | cout << CUBE(10) << endl; 42 | cout << CUBE(15) << endl; 43 | 44 | #undef CUBE 45 | 46 | #ifdef AUTH_PWD 47 | # undef AUTH_PWD 48 | #endif 49 | #define AUTH_PWD "xxx" 50 | 51 | cout << AUTH_PWD << endl; 52 | 53 | #define MAX_BUF_LEN 65535 54 | #define VERSION "1.0.18" 55 | } 56 | 57 | // macro for convienient namespace 58 | #define BEGIN_NAMESPACE(x) namespace x { 59 | #define END_NAMESPACE(x) } 60 | 61 | BEGIN_NAMESPACE(my_own) 62 | 63 | class MyClass final 64 | { 65 | }; 66 | 67 | void case3() 68 | { 69 | cout << "working in own namespace" << endl; 70 | } 71 | 72 | END_NAMESPACE(my_own) 73 | 74 | #ifdef __cplusplus 75 | extern "C" { 76 | #endif 77 | void a_c_function(int a); 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | 82 | void case4() 83 | { 84 | 85 | cout << __cplusplus << endl; 86 | 87 | #if __cplusplus >= 202002 88 | cout << "c++20 or later" << endl; 89 | #elif __cplusplus >= 201703 90 | cout << "c++17 or later" << endl; 91 | #else // __cplusplus < 201703 92 | # error "c++ is too old" 93 | #endif // __cplusplus >= 202002 94 | 95 | #if __GNUC__ <= 5 96 | cout << "gcc is too old" << endl; 97 | #else // __GNUC__ > 5 98 | cout << "gcc is good enough" << endl; 99 | #endif // __GNUC__ <= 5 100 | 101 | #if defined(__SSE4_2__) && defined(__x86_64) 102 | cout << "we can do more optimization" << endl; 103 | #endif // defined(__SSE4_2__) && defined(__x86_64) 104 | 105 | #if __linux__ 106 | cout << "running on linux" << endl; 107 | #else // not linux 108 | cout << "running on others" << endl; 109 | #endif //__linux__ 110 | 111 | #if defined(__cpp_modules) 112 | cout << "moudle enable" << endl; 113 | #else 114 | cout << "moudle disable" << endl; 115 | #endif 116 | 117 | #if defined(__cpp_decltype_auto) 118 | cout << "decltype(auto) enable" << endl; 119 | #else 120 | cout << "decltype(auto) disable" << endl; 121 | #endif //__cpp_decltype_auto 122 | 123 | #ifndef NDEBUG 124 | cout << "debug mode" << endl; 125 | #endif // NDEBUG 126 | 127 | } 128 | 129 | int main() 130 | { 131 | case1(); 132 | case2(); 133 | 134 | my_own::case3(); 135 | 136 | //[[gnu::unused]] // ignore warning 137 | [[maybe_unused]] // ignore warning 138 | my_own::MyClass obj; 139 | 140 | case4(); 141 | 142 | cout << "pre-process demo" << endl; 143 | } 144 | -------------------------------------------------------------------------------- /ch2/static_assert.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ static_assert.cpp -Werror -std=c++17 -o a.out;./a.out 4 | // g++ static_assert.cpp -Werror -std=c++20 -o a.out;./a.out 5 | // 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | void case1() 14 | { 15 | int i = 10; 16 | int *p = &i; 17 | 18 | assert(i > 0 && "i must be greater than zero"); 19 | assert(p != nullptr); 20 | 21 | std::string str = "hello"; 22 | assert(!str.empty()); 23 | } 24 | 25 | void case2() 26 | { 27 | static_assert(sizeof(int) == 4, "int must be 32bit"); 28 | static_assert(sizeof(long) >= 8, "must run on x64"); 29 | } 30 | 31 | template 32 | void check_type(T v) 33 | { 34 | using namespace std; 35 | 36 | //static_assert(is_integral_v, "int"); 37 | static_assert(is_pointer_v, "ptr"); 38 | //static_assert(is_default_constructible_v, "is_default_constructible"); 39 | 40 | cout << "static_assert : " << typeid(v).name() << endl; 41 | 42 | cout << is_void_v << endl; 43 | } 44 | 45 | int main() 46 | { 47 | using namespace std; 48 | 49 | case1(); 50 | case2(); 51 | 52 | //check_type(10); 53 | check_type((void*)0); 54 | 55 | cout << "static_assert demo" << endl; 56 | } 57 | -------------------------------------------------------------------------------- /ch3/auto.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ auto.cpp -std=c++17 -o a.out;./a.out 4 | // g++ auto.cpp -std=c++20 -o a.out;./a.out 5 | // g++ auto.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | 21 | void case1() 22 | { 23 | 24 | int i = 0; 25 | double x = 1.0; 26 | 27 | std::string str = "hello"; 28 | std::map m = {{1,"a"}, {2,"b"}}; 29 | 30 | std::map::const_iterator iter = m.begin(); 31 | 32 | //using namespace std; 33 | //cout << i << x; 34 | } 35 | 36 | void case2() 37 | { 38 | using namespace std; 39 | 40 | auto i = 0; 41 | //auto i{0} ; 42 | auto x = 1.0; 43 | 44 | auto str = "hello"s; 45 | //auto str = "hello"; 46 | //decltype("hello") str = "hello"; 47 | 48 | std::map m = {{1,"a"}, {2,"b"}}; 49 | 50 | auto iter = m.begin(); 51 | 52 | //auto f = bind1st(std::less(), 2); 53 | using namespace std::placeholders; 54 | auto f = bind(std::less(), _1); 55 | 56 | //using namespace std; 57 | //cout << typeid(str).name() << endl; 58 | } 59 | 60 | void case3() 61 | { 62 | auto x = 0L; 63 | auto y = &x; 64 | auto z {&x}; 65 | } 66 | 67 | class X final 68 | { 69 | //auto a = 10; 70 | int a = 10; 71 | }; 72 | 73 | void case4() 74 | { 75 | auto x = 10L; 76 | 77 | auto& x1 = x; 78 | auto* x2 = &x; 79 | const auto& x3 = x; 80 | auto x4 = &x3; 81 | auto&& x5 = x; 82 | 83 | using namespace std; 84 | 85 | cout << *x2 << endl; 86 | cout << *x4 << endl; 87 | //cout << typeid(x4).name() << endl; 88 | //cout << typeid(x5).name() << endl; 89 | static_assert(is_reference_v); 90 | static_assert(is_pointer_v); 91 | static_assert(is_reference_v); 92 | } 93 | 94 | void case5() 95 | { 96 | int x = 0; 97 | 98 | decltype(x) x1; 99 | decltype(x)& x2 = x; 100 | decltype(x)* x3; 101 | decltype(&x) x4; 102 | decltype(&x)* x5; 103 | decltype(x2) x6 = x2; 104 | auto x7 = x2; 105 | 106 | using int_ptr = decltype(&x); 107 | using int_ref = decltype(x)&; 108 | } 109 | 110 | void case6() 111 | { 112 | int x = 0; 113 | 114 | decltype(auto) x1 = (x); 115 | decltype(auto) x2 = &x; 116 | decltype(auto) x3 = x1; 117 | 118 | assert(std::is_lvalue_reference_v); 119 | assert(std::is_pointer_v); 120 | assert(std::is_lvalue_reference_v); 121 | } 122 | 123 | auto get_a_set() 124 | { 125 | std::set s = {1,2,3}; 126 | 127 | return s; 128 | } 129 | 130 | void case7() 131 | { 132 | using namespace std; 133 | 134 | vector v = {2,3,5,7,11}; 135 | 136 | for(const auto& i : v) { 137 | cout << i << ","; 138 | } 139 | cout << endl; 140 | 141 | for(auto& i : v) { 142 | i++; 143 | cout << i << ","; 144 | } 145 | cout << endl; 146 | 147 | //tuple x {1, "x", 0.1}; 148 | tuple x {1, "x"s, 0.1}; 149 | auto [a, b, c] = x; 150 | 151 | //int a; string b; double c; 152 | //std::tie(a, b, c) = x; 153 | 154 | assert(a == 1 && b == "x"); 155 | 156 | std::map m = {{1,"a"}, {2,"b"}}; 157 | 158 | for (auto& [k,v] : m) { 159 | cout << k << "=>" << v << endl; 160 | } 161 | } 162 | 163 | class DemoClass final 164 | { 165 | public: 166 | using sig_func_ptr_t = decltype(&signal) ; 167 | public: 168 | using set_type = std::set; 169 | 170 | private: 171 | set_type m_set; 172 | 173 | using iter_type = decltype(m_set.begin()); 174 | iter_type m_pos; 175 | }; 176 | 177 | int main() 178 | { 179 | using namespace std; 180 | 181 | case1(); 182 | case2(); 183 | case3(); 184 | case4(); 185 | case5(); 186 | case6(); 187 | case7(); 188 | 189 | cout << "auto/decltype demo" << endl; 190 | } 191 | -------------------------------------------------------------------------------- /ch3/const.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ const.cpp -std=c++17 -o a.out;./a.out 4 | // g++ const.cpp -std=c++20 -o a.out;./a.out 5 | // g++ const.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | void case1() 15 | { 16 | using namespace std; 17 | 18 | //const int MAX_LEN = 1024; 19 | const volatile int MAX_LEN = 1024; 20 | const std::string NAME = "metroid"; 21 | 22 | //auto ptr = (int*)(&MAX_LEN); 23 | auto ptr = const_cast(&MAX_LEN); 24 | *ptr = 2048; 25 | cout << MAX_LEN << endl; 26 | 27 | } 28 | 29 | void case2() 30 | { 31 | using namespace std; 32 | 33 | int x = 100; 34 | 35 | const int& rx = x; 36 | const int* px = &x; 37 | 38 | cout << rx << *px << endl; 39 | 40 | string name = "uncharted"; 41 | 42 | const string* ps1 = &name; 43 | //*ps1 = "spiderman"; 44 | 45 | cout << *ps1 << endl; 46 | 47 | string* const ps2 = &name; 48 | *ps2 = "spiderman"; 49 | 50 | cout << *ps2 << endl; 51 | 52 | const string* const ps3 = &name; 53 | 54 | //auto&& s = std::as_const(name); 55 | decltype(auto) s = std::as_const(name); 56 | assert(std::is_const_v< 57 | std::remove_reference_t 58 | >); 59 | assert(std::is_reference_v); 60 | } 61 | 62 | class DemoClass final 63 | { 64 | private: 65 | using mutex_type = int; // dummy type 66 | private: 67 | mutable mutex_type m_mutex; 68 | 69 | const long MAX_SIZE = 256; 70 | int m_value = 100; 71 | public: 72 | int get_value() const 73 | { 74 | return m_value; 75 | } 76 | 77 | void incr() 78 | { 79 | m_value++; 80 | } 81 | 82 | void save_data() const 83 | { 84 | m_mutex++; 85 | //m_value++; 86 | } 87 | }; 88 | 89 | void case3() 90 | { 91 | using namespace std; 92 | 93 | DemoClass obj; 94 | //const auto& cobj = obj; 95 | //decltype(auto) cobj = std::as_const(obj); 96 | auto&& cobj = std::as_const(obj); 97 | 98 | cout << cobj.get_value() << endl; 99 | //cobj.incr(); 100 | cobj.save_data(); 101 | } 102 | 103 | 104 | int main() 105 | { 106 | using namespace std; 107 | 108 | case1(); 109 | case2(); 110 | case3(); 111 | 112 | cout << "const demo" << endl; 113 | } 114 | -------------------------------------------------------------------------------- /ch3/constexpr.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ constexpr.cpp -std=c++17 -o a.out;./a.out 4 | // g++ constexpr.cpp -std=c++20 -o a.out;./a.out 5 | // g++ constexpr.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | constexpr 19 | long mega_bits() 20 | { 21 | return 1024*1024; 22 | } 23 | 24 | void case1() 25 | { 26 | using namespace std; 27 | 28 | constexpr int MAX = 100; 29 | 30 | array arr = {0}; 31 | assert(arr.size() == 100); 32 | 33 | static_assert(mega_bits() == 1024*1024); 34 | bitset bits; 35 | } 36 | 37 | void case2() 38 | { 39 | 40 | using namespace std; 41 | 42 | constexpr auto val = 100; 43 | constexpr auto str = "hello"; 44 | constexpr array arr {1,2,3}; 45 | 46 | //constexpr vector vec {1,2,3}; 47 | //constexpr string s = "str"; 48 | //constexpr map m; 49 | 50 | } 51 | 52 | constexpr 53 | int fib(int n) 54 | { 55 | if (n == 0 || n == 1) { 56 | return 1; 57 | } 58 | 59 | return fib(n - 1) + fib(n - 2); 60 | } 61 | 62 | void case3() 63 | { 64 | static_assert(fib(4) == 5); 65 | static_assert(fib(5) == 8); 66 | } 67 | 68 | constexpr 69 | void case4() 70 | { 71 | #if __cplusplus > 201703 72 | 73 | using namespace std; 74 | 75 | //vector vec {1,2,3}; 76 | //string s = "str"; 77 | 78 | auto x = new char[10]; 79 | delete[] x; 80 | 81 | try { 82 | int a = 10; 83 | } 84 | catch(...) 85 | { 86 | } 87 | 88 | #endif 89 | } 90 | 91 | int main() 92 | { 93 | using namespace std; 94 | 95 | case1(); 96 | case2(); 97 | case3(); 98 | 99 | cout << "constexpr demo" << endl; 100 | } 101 | -------------------------------------------------------------------------------- /ch3/exception.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ exception.cpp -std=c++17 -o a.out;./a.out 4 | // g++ exception.cpp -std=c++20 -o a.out;./a.out 5 | // g++ exception.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | class my_exception : public std::runtime_error 13 | { 14 | public: 15 | using this_type = my_exception; 16 | using super_type = std::runtime_error; 17 | public: 18 | my_exception(const char* msg): 19 | super_type(msg) 20 | {} 21 | 22 | my_exception() = default; 23 | ~my_exception() = default; 24 | private: 25 | int code = 0; 26 | }; 27 | 28 | [[noreturn]] 29 | void raise(const char* msg) 30 | { 31 | throw my_exception(msg); 32 | //throw runtime_error(msg); 33 | } 34 | 35 | void case1() 36 | try 37 | { 38 | raise("error occured"); 39 | } 40 | catch(const exception& e) 41 | { 42 | cout << e.what() << endl; 43 | } 44 | 45 | void case2() noexcept 46 | { 47 | cout << "noexcept" << endl; 48 | } 49 | 50 | void case3() noexcept 51 | { 52 | throw "Oh My God"; 53 | } 54 | 55 | int main() 56 | { 57 | case1(); 58 | case2(); 59 | //case3(); 60 | 61 | cout << "exception demo" << endl; 62 | } 63 | -------------------------------------------------------------------------------- /ch3/lambda.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ lambda.cpp -std=c++17 -o a.out;./a.out 4 | // g++ lambda.cpp -std=c++20 -o a.out;./a.out 5 | // g++ lambda.cpp -std=c++20 -I../common -o a.out;./a.out 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | void my_square(int x) 16 | { 17 | cout << x*x << endl; 18 | } 19 | 20 | void case1() 21 | { 22 | auto pfunc = &my_square; 23 | 24 | (*pfunc)(3); 25 | pfunc(3); 26 | 27 | auto func = [](int x) 28 | { 29 | cout << x*x << endl; 30 | }; 31 | 32 | func(3); 33 | } 34 | 35 | void case2() 36 | { 37 | int n = 10; 38 | 39 | auto func = [=](int x) 40 | { 41 | cout << x*n << endl; 42 | }; 43 | 44 | func(3); 45 | } 46 | 47 | void case3() 48 | { 49 | auto f1 = [](){}; 50 | 51 | auto f2 = []() 52 | { 53 | cout << "lambda f2" << endl; 54 | 55 | auto f3 = [](int x) 56 | { 57 | return x*x; 58 | };// lambda f3 59 | 60 | cout << f3(10) << endl; 61 | }; // lambda f2 62 | 63 | f1(); 64 | f2(); 65 | 66 | //f1 = f2; 67 | 68 | vector v = {3, 1, 8, 5, 0}; 69 | 70 | cout << *find_if(begin(v), end(v), 71 | [](int x) 72 | { 73 | return x >= 5; 74 | } 75 | ) 76 | << endl; 77 | 78 | auto f3 = [](long x) -> int 79 | { 80 | return static_cast(x); 81 | }; 82 | 83 | cout << f3(10L) << endl; 84 | } 85 | 86 | void case4() 87 | { 88 | int x = 33; 89 | 90 | auto f1 = [=]() 91 | { 92 | //x += 10; 93 | cout << x << endl; 94 | }; 95 | 96 | auto f2 = [&]() 97 | { 98 | x += 10; 99 | }; 100 | 101 | auto f3 = [=, &x]() 102 | { 103 | x += 20; 104 | }; 105 | 106 | auto f4 = [=]() mutable 107 | { 108 | x += 10; 109 | }; 110 | 111 | f1(); 112 | f2(); 113 | cout << x << endl; 114 | f3(); 115 | cout << x << endl; 116 | f4(); 117 | cout << x << endl; 118 | } 119 | 120 | class DemoLambda final 121 | { 122 | public: 123 | DemoLambda() = default; 124 | ~DemoLambda() = default; 125 | private: 126 | int x = 0; 127 | public: 128 | auto print() 129 | { 130 | //auto f = [=]() 131 | 132 | return [this]() 133 | { 134 | cout << "member = " << x << endl; 135 | }; 136 | 137 | } 138 | }; 139 | 140 | void case5() 141 | { 142 | DemoLambda obj; 143 | 144 | auto f = obj.print(); 145 | 146 | f(); 147 | } 148 | 149 | void case6() 150 | { 151 | auto f = [](const auto& x) 152 | { 153 | return x + x; 154 | }; 155 | 156 | cout << f(3) << endl; 157 | cout << f(0.618) << endl; 158 | 159 | string str = "matrix"; 160 | cout << f(str) << endl; 161 | 162 | } 163 | 164 | void case7() 165 | { 166 | #if __cplusplus >=202002 167 | auto f = [](const T& x) 168 | { 169 | static_assert(is_integral_v) 170 | return x + x; 171 | }; 172 | 173 | cout << f(3) << endl; 174 | 175 | #endif 176 | } 177 | // demo for function + lambda 178 | class Demo final 179 | { 180 | public: 181 | using func_type = std::function; 182 | public: 183 | func_type print = [this]() 184 | { 185 | cout << "value = " << m_value << endl; 186 | cout << "hello function+lambda" << endl; 187 | }; 188 | private: 189 | int m_value = 10; 190 | }; 191 | 192 | int main() 193 | { 194 | case1(); 195 | case2(); 196 | case3(); 197 | case4(); 198 | case5(); 199 | case6(); 200 | case7(); 201 | 202 | Demo d; 203 | d.print(); 204 | 205 | cout << "lambda demo" << endl; 206 | } 207 | -------------------------------------------------------------------------------- /ch3/oop.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ oop.cpp -std=c++17 -o a.out;./a.out 4 | // g++ oop.cpp -std=c++20 -o a.out;./a.out 5 | // 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #if 1 13 | 14 | class Interface {}; 15 | 16 | class Implement final : public Interface 17 | { 18 | public: 19 | using super_type = Interface; 20 | using this_type = Implement; 21 | private: 22 | }; 23 | 24 | #endif 25 | 26 | #if 1 27 | 28 | struct KafkaConfig final 29 | { 30 | int id; 31 | std::string ip_addr; 32 | }; 33 | 34 | class DemoClass final 35 | { 36 | public: 37 | using this_type = DemoClass; 38 | using kafka_conf_type = KafkaConfig; 39 | 40 | public: 41 | using string_type = std::string; 42 | using uint32_type = uint32_t; 43 | 44 | using set_type = std::set; 45 | using vector_type = std::vector; 46 | 47 | public: 48 | DemoClass() = default; 49 | ~DemoClass() = default; 50 | 51 | DemoClass(const DemoClass&) = delete; 52 | DemoClass& operator=(const DemoClass&) = delete; 53 | public: 54 | explicit DemoClass(const string_type& str) 55 | { 56 | m_name = str; 57 | } 58 | explicit operator bool () 59 | { 60 | return !m_name.empty(); 61 | } 62 | public: 63 | void set_name(const string_type& str); 64 | 65 | private: 66 | string_type m_name = "tom"; 67 | uint32_type m_age = 23; 68 | set_type m_books; 69 | 70 | private: 71 | kafka_conf_type m_conf; 72 | }; 73 | 74 | #endif 75 | 76 | #if 1 77 | 78 | class DemoDelegating final 79 | { 80 | private: 81 | int a; 82 | public: 83 | DemoDelegating(int x) : a(x) 84 | {} 85 | 86 | DemoDelegating() : DemoDelegating(0) 87 | {} 88 | 89 | DemoDelegating(const std::string& s) : DemoDelegating(std::stoi(s)) 90 | {} 91 | }; 92 | 93 | #endif 94 | 95 | #if 1 96 | 97 | class DemoInit final 98 | { 99 | private: 100 | int a = 0; 101 | std::string s = "hello"; 102 | std::vector v{1, 2, 3}; 103 | public: 104 | static const 105 | int x = 0; 106 | 107 | inline static 108 | std::string prefix = "/home"; 109 | //static std::string prefix; 110 | public: 111 | DemoInit() = default; 112 | ~DemoInit() = default; 113 | public: 114 | DemoInit(int x) : a(x) {} 115 | }; 116 | //std::string DemoInit::prefix = "/home"; 117 | 118 | #endif 119 | 120 | 121 | int main() 122 | { 123 | using namespace std; 124 | 125 | //DemoClass obj = "sting ctor"; 126 | DemoClass obj = (DemoClass)"sting ctor"; 127 | 128 | //bool b = obj; 129 | bool b = static_cast(obj); 130 | if (obj) { 131 | cout << "explicit bool ok" << endl; 132 | } 133 | 134 | cout << DemoInit::prefix << endl; 135 | 136 | cout << "show your class." << endl; 137 | } 138 | -------------------------------------------------------------------------------- /ch3/others.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ others.cpp -std=c++17 -o a.out;./a.out 4 | // g++ others.cpp -std=c++20 -o a.out;./a.out 5 | // 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | inline namespace tmp{ 15 | auto x = 0L; 16 | auto str = "hello"; 17 | } 18 | 19 | void case1() 20 | { 21 | using namespace std; 22 | 23 | cout << x << endl; 24 | cout << tmp::str << endl; 25 | } 26 | 27 | namespace a::b::c { 28 | auto str = "namespace"; 29 | } 30 | 31 | void case2() 32 | { 33 | using namespace std; 34 | 35 | cout << a::b::c::str << endl; 36 | } 37 | 38 | enum class Company { 39 | Apple, Google, Facebook 40 | }; 41 | 42 | void case3() 43 | { 44 | using namespace std; 45 | 46 | //Company x = 1; 47 | 48 | auto v = Company::Apple; 49 | 50 | //int i = v; 51 | auto i = static_cast(v); 52 | 53 | cout << i << endl; 54 | } 55 | 56 | void case4() 57 | { 58 | using namespace std; 59 | 60 | for(int i = 0;i < 3;i++) { 61 | cout << "hello world" << endl; 62 | } 63 | 64 | vector v {1,2,3}; 65 | if (auto pos = v.end(); !v.empty()) { 66 | cout << pos - v.begin() << endl; 67 | } 68 | 69 | for (auto pos = v.end(); !v.empty();) { 70 | cout << pos - v.begin() << endl; 71 | break; 72 | } 73 | } 74 | 75 | void case5() 76 | { 77 | using namespace std; 78 | 79 | auto a = 10; 80 | auto b = 010; 81 | auto c = 0x10; 82 | 83 | assert(a == 10 && b == 8 && c == 16); 84 | cout << a << b << c << endl; 85 | 86 | auto x = 0b11010010; 87 | //cout << x << endl; 88 | assert(x == 0xD2); 89 | } 90 | 91 | void case6() 92 | { 93 | using namespace std; 94 | 95 | auto a = 0b1011'0101; 96 | auto b = 07'6'6; 97 | auto c = 1'000'000; 98 | auto d = 0xFA'BE'03; 99 | auto e = 9'777'1'88'10; 100 | 101 | cout << a << b << c << d << endl; 102 | } 103 | 104 | 105 | int main() 106 | { 107 | using namespace std; 108 | 109 | case1(); 110 | case2(); 111 | case3(); 112 | case4(); 113 | case5(); 114 | case6(); 115 | 116 | cout << "others demo" << endl; 117 | } 118 | -------------------------------------------------------------------------------- /ch4/algo.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ algo.cpp -std=c++17 -o a.out;./a.out 4 | // g++ algo.cpp -std=c++20 -o a.out;./a.out 5 | // g++ algo.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void case1() 20 | { 21 | vector v = {1,3,1,7,5}; 22 | 23 | auto n1 = std::count( 24 | begin(v), end(v), 1 25 | ); 26 | 27 | int n2 = 0; 28 | for(auto& x : v) { 29 | if (x == 1) { 30 | n2++; 31 | } 32 | } 33 | 34 | assert(n1 == n2); 35 | 36 | auto n = std::count_if( 37 | begin(v), end(v), 38 | [](auto x) { 39 | return x > 2; 40 | } 41 | ); 42 | 43 | assert(n == 3); 44 | } 45 | 46 | void case2() 47 | { 48 | vector v = {1,2,3,4,5}; 49 | 50 | auto iter1 = v.begin(); 51 | auto iter2 = v.end(); 52 | 53 | auto iter3 = std::begin(v); 54 | auto iter4 = std::end(v); 55 | 56 | assert(iter1 == iter3); 57 | assert(iter2 == iter4); 58 | } 59 | 60 | void case3() 61 | { 62 | array arr = {0,1,2,3,4}; 63 | 64 | auto b = begin(arr); 65 | auto e = end(arr); 66 | 67 | assert(distance(b, e) == 5); 68 | 69 | auto p = next(b); 70 | assert(distance(b, p) == 1); 71 | assert(distance(p, b) == -1); 72 | 73 | advance(p, 2); 74 | assert(*p == 3); 75 | assert(p == prev(e, 2)); 76 | 77 | } 78 | 79 | 80 | int main() 81 | { 82 | case1(); 83 | case2(); 84 | case3(); 85 | 86 | using namespace std; 87 | 88 | cout << "algorithm demo" << endl; 89 | } 90 | -------------------------------------------------------------------------------- /ch4/any.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ any.cpp -std=c++17 -o a.out;./a.out 4 | // g++ any.cpp -std=c++20 -o a.out;./a.out 5 | // g++ any.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | void case1() 17 | { 18 | any a; 19 | 20 | a = 10; 21 | a = 0.618; 22 | a = "hello any"s; 23 | a = vector(10); 24 | 25 | //cout << a.type().name() << endl; 26 | 27 | } 28 | 29 | void case2() 30 | { 31 | auto a = make_any(99); 32 | assert(a.has_value()); 33 | 34 | a.reset(); 35 | assert(!a.has_value()); 36 | } 37 | 38 | void case3() 39 | { 40 | any a; 41 | 42 | a = 100L; 43 | assert(any_cast(a) == 100); 44 | 45 | auto& v = any_cast(a); 46 | v = 200L; 47 | assert(any_cast(a) == 200); 48 | 49 | a = "any"s; 50 | 51 | auto p = any_cast(&a); 52 | //cout << *p << endl; 53 | assert(p && p->size() == 3); 54 | 55 | //any_cast(a); 56 | assert(any_cast(&a) == nullptr); 57 | } 58 | 59 | void case4() 60 | { 61 | any a; 62 | 63 | a = 10; 64 | assert(a.type() == typeid(int)); 65 | 66 | a = "string"s; 67 | assert(a.type() == typeid(string)); 68 | 69 | if (a.type() == typeid(long)) { 70 | cout << "do with long"<< endl; 71 | } 72 | 73 | a = 100L; 74 | 75 | if (auto p = any_cast(&a); p) { 76 | cout << *p << endl; 77 | } 78 | } 79 | 80 | int main() 81 | { 82 | case1(); 83 | case2(); 84 | case3(); 85 | case4(); 86 | 87 | cout << "any demo" << endl; 88 | } 89 | -------------------------------------------------------------------------------- /ch4/async.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ async.cpp -lpthread -std=c++17 -o a.out;./a.out 4 | // g++ async.cpp -lpthread -std=c++20 -o a.out;./a.out 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | void case1() 18 | { 19 | auto task = [](auto x) 20 | { 21 | //using namespace std::chrono_literals; 22 | 23 | this_thread::sleep_for( x * 1ms); 24 | 25 | cout << "sleep for " << x << endl; 26 | 27 | return x; 28 | }; 29 | 30 | auto f = std::async(task, 10); 31 | 32 | f.wait(); 33 | 34 | //cout << f.valid() << endl; 35 | 36 | assert(f.valid()); 37 | cout << f.get() << endl; 38 | assert(!f.valid()); 39 | 40 | //cout << f.get() << endl; 41 | //cout << f.valid() << endl; 42 | } 43 | 44 | int main() 45 | { 46 | case1(); 47 | //case2(); 48 | 49 | cout << "async demo" << endl; 50 | } 51 | -------------------------------------------------------------------------------- /ch4/atomic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ atomic.cpp -lpthread -std=c++17 -o a.out;./a.out 4 | // g++ atomic.cpp -lpthread -std=c++20 -o a.out;./a.out 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | 16 | void case1() 17 | { 18 | atomic_int x {0}; 19 | atomic_long y {1000L}; 20 | 21 | assert(++x == 1); 22 | y += 200; 23 | assert(y < 2000); 24 | } 25 | 26 | void case2() 27 | { 28 | atomic_uint x {0}; 29 | 30 | x.store(10); 31 | assert(x.load() == 10); 32 | 33 | auto v = x.fetch_add(5); 34 | assert(v == 10 && x == 15); 35 | 36 | v = x.fetch_sub(2); 37 | assert(v == 15 && x == 13); 38 | 39 | auto u = x.exchange(100); 40 | assert(u == 13 && x == 100); 41 | 42 | unsigned int w = 100; 43 | auto flag = x.compare_exchange_strong(w, 42); 44 | assert(flag && x == 42); 45 | 46 | w = 0; 47 | flag = x.compare_exchange_strong(w, 10); 48 | assert(!flag && w == 42); 49 | } 50 | 51 | void case3() 52 | { 53 | static atomic_flag flag {false}; 54 | static atomic_int n; 55 | 56 | auto f = [&]() 57 | { 58 | auto value = flag.test_and_set(); 59 | 60 | if (value) { 61 | cout << "flag has been set." << endl; 62 | } else { 63 | cout << "set flag by " << 64 | this_thread::get_id() << endl; 65 | } 66 | 67 | n += 100; 68 | 69 | //using namespace std::chrono_literals; 70 | 71 | this_thread::sleep_for(n.load() * 10ms); 72 | cout << n << endl; 73 | 74 | }; 75 | 76 | thread t1(f); 77 | thread t2(f); 78 | 79 | t1.join(); 80 | t2.join(); 81 | } 82 | 83 | 84 | int main() 85 | { 86 | case1(); 87 | case2(); 88 | case3(); 89 | 90 | cout << "atomic demo" << endl; 91 | } 92 | -------------------------------------------------------------------------------- /ch4/call_once.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ call_once.cpp -lpthread -std=c++17 -o a.out;./a.out 4 | // g++ call_once.cpp -lpthread -std=c++20 -o a.out;./a.out 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | void case1() 16 | { 17 | static once_flag flag; 18 | 19 | auto f = []() 20 | { 21 | cout << "tid=" << 22 | this_thread::get_id() << endl; 23 | 24 | std::call_once(flag, 25 | [](){ 26 | cout << "only once" << endl; 27 | } 28 | ); 29 | }; 30 | 31 | thread t1(f); 32 | thread t2(f); 33 | 34 | t1.join(); 35 | t2.join(); 36 | } 37 | 38 | 39 | int main() 40 | { 41 | case1(); 42 | 43 | cout << "call_once demo" << endl; 44 | } 45 | -------------------------------------------------------------------------------- /ch4/container.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ container.cpp -std=c++17 -o a.out;./a.out 4 | // g++ container.cpp -std=c++20 -o a.out;./a.out 5 | // g++ container.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace std; 22 | 23 | class Point final 24 | { 25 | //private: 26 | public: 27 | int x = 0; 28 | public: 29 | Point(int a) noexcept : x(a) 30 | { 31 | cout << "ctor" << x << endl; 32 | } 33 | 34 | Point() noexcept 35 | { 36 | cout << "ctor" << x << endl; 37 | } 38 | 39 | ~Point() noexcept 40 | { 41 | cout << "dtor" << x << endl; 42 | } 43 | 44 | Point(const Point& p) noexcept 45 | { 46 | x = p.x; 47 | cout << "copy ctor"<< x << endl; 48 | } 49 | 50 | Point(Point&& p) noexcept 51 | { 52 | x = std::move(p.x); 53 | cout << "move ctor" << x << endl; 54 | } 55 | }; 56 | 57 | void case1() 58 | { 59 | vector v; 60 | v.reserve(10); 61 | 62 | Point p; 63 | 64 | v.push_back(p); 65 | v.push_back(std::move(p)); 66 | 67 | v.emplace_back(1); 68 | } 69 | 70 | void case2() 71 | { 72 | array arr; 73 | assert(arr.size() == 2); 74 | 75 | vector v(2); 76 | for(int i = 0; i < 10; i++) { 77 | v.emplace_back(i); 78 | } 79 | //cout << v.size() << endl; 80 | assert(v.size() == 12); 81 | 82 | deque d; 83 | d.emplace_back(9); 84 | d.emplace_front(1); 85 | assert(d.size() == 2); 86 | } 87 | 88 | bool operator<(const Point& a, const Point& b) 89 | { 90 | return a.x < b.x; 91 | } 92 | 93 | void case3() 94 | { 95 | set s; 96 | 97 | s.emplace(7); 98 | s.emplace(3); 99 | 100 | for(auto& p : s) { 101 | cout << p.x << ","; 102 | } 103 | cout << endl; 104 | } 105 | 106 | #if 0 107 | using complex_t = complex; 108 | 109 | // add < compare to complex 110 | namespace std{ 111 | bool operator<(const complex_t& a, const complex_t& b) 112 | { 113 | return a.real() < b.real(); 114 | } 115 | } 116 | 117 | void case3() 118 | { 119 | set s; 120 | 121 | s.emplace(3, 1); 122 | s.emplace(1, 1); 123 | 124 | for(auto& c : s) { 125 | cout << c << ","; 126 | } 127 | cout << endl; 128 | } 129 | #endif 130 | 131 | void case4() 132 | { 133 | set s = {7, 3, 9}; 134 | 135 | for(auto& x : s) { 136 | cout << x << ","; 137 | } 138 | cout << endl; 139 | 140 | auto comp = [](auto&& a, auto&& b) 141 | { 142 | return a > b; 143 | }; 144 | 145 | set gs(comp); 146 | 147 | std::copy(begin(s), end(s), 148 | inserter(gs, gs.end())); 149 | 150 | for(auto& x : gs) { 151 | cout << x << ","; 152 | } 153 | cout << endl; 154 | } 155 | 156 | void case5() 157 | { 158 | using map_type = 159 | unordered_map; 160 | 161 | map_type dict; 162 | 163 | dict[1] = "one"; 164 | dict.emplace(2, "two"); 165 | dict[10] = "ten"; 166 | 167 | for(auto& x : dict) { 168 | cout << x.first << "=>" 169 | << x.second << ","; 170 | } 171 | cout << endl; 172 | } 173 | 174 | bool operator==(const Point& a, const Point& b) 175 | { 176 | return a.x == b.x; 177 | } 178 | 179 | void case6() 180 | { 181 | auto hasher = [](const auto& p) 182 | { 183 | return std::hash()(p.x); 184 | }; 185 | 186 | unordered_set s(10, hasher); 187 | 188 | s.emplace(7); 189 | s.emplace(3); 190 | 191 | for(auto& p : s) { 192 | cout << p.x << ","; 193 | } 194 | cout << endl; 195 | } 196 | 197 | void vector_capacity() 198 | { 199 | constexpr int N = 5; 200 | 201 | vector v(N); 202 | cout << v.capacity() << endl; 203 | 204 | for (int i = 0;i < 2*N; i++) { 205 | v.push_back(i); 206 | } 207 | 208 | cout << v.size() << endl; 209 | cout << v.capacity() << endl; 210 | } 211 | 212 | 213 | int main() 214 | { 215 | case1(); 216 | case2(); 217 | case3(); 218 | case4(); 219 | case5(); 220 | case6(); 221 | 222 | cout << "containter demo" << endl; 223 | } 224 | -------------------------------------------------------------------------------- /ch4/filesystem.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ filesystem.cpp -std=c++17 -lstdc++fs -o a.out;./a.out 4 | // g++ filesystem.cpp -std=c++20 -o a.out;./a.out 5 | 6 | #include 7 | 8 | #include 9 | 10 | #if __has_include() 11 | #include 12 | using namespace std::filesystem; 13 | #else 14 | #include 15 | using namespace std::experimental::filesystem; 16 | #endif 17 | 18 | 19 | void case1() 20 | { 21 | } 22 | 23 | int main() 24 | { 25 | case1(); 26 | 27 | using namespace std; 28 | 29 | cout << "filesystem demo" << endl; 30 | } 31 | -------------------------------------------------------------------------------- /ch4/fmt.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ fmt.cpp -std=c++20 -o a.out;./a.out 4 | // 5 | // g++ fmt.cpp -std=c++17 -lspdlog -lpthread -o a.out;./a.out 6 | // g++ fmt.cpp -std=c++20 -lspdlog -lpthread -o a.out;./a.out 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | //#if __has_include() 14 | //#include 15 | //#else 16 | //#error "no std::format" 17 | //#endif 18 | 19 | #if __has_include() 20 | #include 21 | #elif __has_include() 22 | #define SPDLOG_COMPILED_LIB 23 | #include 24 | #else 25 | #error "no format lib for demo" 26 | #endif 27 | 28 | 29 | void case1() 30 | { 31 | using namespace std; 32 | 33 | #if defined(SPDLOG_COMPILED_LIB) 34 | using namespace fmt; 35 | cout << "using fmtlib implement" << endl; 36 | #endif 37 | 38 | cout << "C++20 format" << endl; 39 | 40 | cout << format("{}", 100L) << endl; 41 | cout << format("{0}-{0}, {1} {2}", 42 | "hello", 2.718, 3.14) <10}", "hello") << endl; 45 | cout << format("{:04}, {:+04}", 100L, 88) << endl; 46 | cout << format("{0:x}, {0:#X}", 100L) << endl; 47 | cout << format("{:04o}, {:04b}", 7, 5) << endl; 48 | 49 | cout << format("see:{{xxx}}") << endl; 50 | 51 | } 52 | 53 | int main() 54 | { 55 | case1(); 56 | 57 | using namespace std; 58 | 59 | cout << "format demo" << endl; 60 | } 61 | -------------------------------------------------------------------------------- /ch4/for_each.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ for_each.cpp -std=c++17 -o a.out;./a.out 4 | // g++ for_each.cpp -std=c++20 -o a.out;./a.out 5 | // g++ for_each.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void case1() 20 | { 21 | #if 1 22 | vector v = {3,5,1,7,10}; 23 | 24 | for(const auto& x : v) { 25 | cout << x << ","; 26 | } 27 | #endif 28 | cout << endl; 29 | 30 | #if 1 31 | auto print = [](const auto& x) 32 | { 33 | cout << x << ","; 34 | }; 35 | 36 | for_each(cbegin(v), cend(v), print); 37 | #endif 38 | cout << endl; 39 | 40 | #if 1 41 | for_each( 42 | cbegin(v), cend(v), 43 | [](const auto& x) 44 | { 45 | cout << x << ","; 46 | } 47 | ); 48 | #endif 49 | cout << endl; 50 | 51 | } 52 | 53 | void case2() 54 | { 55 | vector v = {3,5,1,7,10}; 56 | 57 | cout << __cplusplus << endl; 58 | // it can not work in gcc 7.5 59 | //#if __cplusplus > 201703 60 | #if __GNUC__ > 7 61 | for_each_n( 62 | cbegin(v), 3, 63 | [](const auto& x) 64 | { 65 | cout << x*x << ","; 66 | } 67 | ); 68 | #else 69 | cout << "for_each_n can not work" << endl; 70 | #endif 71 | cout << endl; 72 | } 73 | 74 | int main() 75 | { 76 | case1(); 77 | case2(); 78 | 79 | using namespace std; 80 | 81 | cout << "for_each demo" << endl; 82 | } 83 | -------------------------------------------------------------------------------- /ch4/optional.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ optional.cpp -std=c++17 -o a.out;./a.out 4 | // g++ optional.cpp -std=c++20 -o a.out;./a.out 5 | // g++ optional.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | void case1() 18 | { 19 | optional op; 20 | assert(!op.has_value()); 21 | 22 | op = 10; 23 | 24 | if (op.has_value()) { 25 | cout << "value is valid" << endl; 26 | } 27 | } 28 | 29 | void case2() 30 | { 31 | optional op1 = 42; 32 | 33 | if (op1.has_value()) { 34 | cout << op1.value() << endl; 35 | } 36 | 37 | optional op2; 38 | cout << op2.value_or(99) << endl; 39 | } 40 | 41 | void case3() 42 | { 43 | optional op {"zelda"}; 44 | assert(op); 45 | assert(!op->empty() && *op == "zelda"); 46 | 47 | op.reset(); 48 | assert(!op); 49 | } 50 | 51 | void case4() 52 | { 53 | auto op1 = make_optional(); 54 | auto op2 = make_optional(); 55 | 56 | assert(op1 && op2); 57 | assert(op1 == 0); 58 | assert(op2->empty()); 59 | 60 | auto op3 = make_optional("hi"); 61 | auto op4 = make_optional>({1,2,3}); 62 | 63 | assert(op3->size() == 2); 64 | assert(op4->at(0) == 1); 65 | } 66 | 67 | void case5() 68 | { 69 | auto safe_sqrt = [](double x) { 70 | optional v; 71 | 72 | if (x < 0) { 73 | return v; 74 | } 75 | 76 | v = ::sqrt(x); 77 | return v; 78 | }; 79 | 80 | assert(!safe_sqrt(-1)); 81 | assert(safe_sqrt(9).value() == 3); 82 | } 83 | 84 | void case6() 85 | { 86 | optional op {false}; 87 | 88 | if (op) { 89 | cout << "misuse of optional" << endl; 90 | } 91 | 92 | if (op && op.value()) { 93 | cout << "right use" << endl; 94 | } 95 | } 96 | 97 | 98 | int main() 99 | { 100 | case1(); 101 | case2(); 102 | case3(); 103 | case4(); 104 | case5(); 105 | case6(); 106 | 107 | cout << "optional demo" << endl; 108 | } 109 | -------------------------------------------------------------------------------- /ch4/par_algo.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ par_algo.cpp -std=c++20 -o a.out;time ./a.out 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #if __has_include() 14 | #include 15 | #else 16 | #error "no header file" 17 | #endif 18 | 19 | #include 20 | #include 21 | 22 | using namespace std; 23 | 24 | namespace ranges = std::ranges; 25 | namespace views = std::views; 26 | 27 | auto print = [](const auto& x){ 28 | cout << x << ","; 29 | }; 30 | 31 | void case1() 32 | { 33 | minstd_rand rand; 34 | vector v(1000 * 10); 35 | 36 | //cout << to_string(rand()); 37 | ranges::generate(v, [&](){ 38 | return to_string(rand()); 39 | }); 40 | 41 | //ranges::for_each(v | views::take(10), print); 42 | 43 | std::sort(execution::par, begin(v), end(v)); 44 | //std::sort(begin(v), end(v)); 45 | 46 | //cout << endl; 47 | } 48 | 49 | 50 | int main() 51 | { 52 | case1(); 53 | 54 | using namespace std; 55 | 56 | cout << "par algorithm demo" << endl; 57 | } 58 | -------------------------------------------------------------------------------- /ch4/ranges.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ ranges.cpp -std=c++20 -o a.out;./a.out 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #if __cplusplus <= 201703L 15 | #error "needs C++20 or higher" 16 | #endif 17 | 18 | #include 19 | #include 20 | 21 | using namespace std; 22 | 23 | namespace ranges = std::ranges; 24 | namespace views = std::views; 25 | 26 | auto print = [](const auto& x){ 27 | cout << x << ","; 28 | }; 29 | 30 | void case1() 31 | { 32 | vector v = {9,5,1,7,3}; 33 | 34 | ranges::for_each(v, print); 35 | cout << endl; 36 | 37 | cout << ranges::count_if( 38 | v, [](auto& x){ 39 | return x >= 5; 40 | }) 41 | << endl; 42 | 43 | ranges::stable_sort(v); 44 | ranges::for_each(v, print); 45 | cout << endl; 46 | 47 | assert(ranges::binary_search(v, 7)); 48 | 49 | auto pos = ranges::lower_bound(v, 3); 50 | assert(pos != end(v) && *pos == 3); 51 | 52 | cout << endl; 53 | } 54 | 55 | void case2() 56 | { 57 | minstd_rand rand; 58 | 59 | vector v = {9,5,1,7,3}; 60 | 61 | ranges::shuffle(v, rand); 62 | cout << endl; 63 | 64 | ranges::partial_sort(v, next(begin(v), 3)); 65 | ranges::for_each(v, print); 66 | 67 | ranges::shuffle(v, rand); 68 | cout << endl; 69 | 70 | auto [mi, ma] = ranges::minmax_element(v); 71 | cout << *mi << "," 72 | << *ma << endl; 73 | cout << endl; 74 | } 75 | 76 | void case3() 77 | { 78 | vector v = {3,7,2,4,9,6,8,1,5}; 79 | 80 | for (auto&& x : v | views::drop(3) | views::reverse) { 81 | cout << x << ","; 82 | } 83 | cout << endl; 84 | 85 | auto r1 = v | views::drop(3); 86 | auto r2 = r1 | views::reverse; 87 | 88 | ranges::for_each(r2, print); 89 | cout << endl; 90 | 91 | cout << endl; 92 | } 93 | 94 | void case4() 95 | { 96 | 97 | vector v = {3,7,2,4,9,6,8,1,5}; 98 | 99 | ranges::for_each(v, print); 100 | cout << endl; 101 | 102 | #if 0 103 | auto r1 = v | views::filter( 104 | [](auto& x) { 105 | return x % 2 == 0; 106 | }) ; 107 | ranges::for_each(r1, print); 108 | cout << endl; 109 | #endif 110 | 111 | ranges::for_each( 112 | v | views::filter( 113 | [](auto& x) { 114 | return x % 2 == 0; 115 | }), 116 | print 117 | ); 118 | cout << endl; 119 | 120 | decltype(v) v2; 121 | ranges::copy(v | views::take(3), back_inserter(v2)); 122 | 123 | ranges::for_each(v2, print); 124 | cout << endl; 125 | 126 | vector> pairs = { 127 | {1, "one"}, {2, "two"}, {3, "three"} 128 | }; 129 | 130 | ranges::for_each( 131 | pairs | views::take(2) | views::values, 132 | print 133 | ); 134 | cout << endl; 135 | 136 | cout << endl; 137 | } 138 | 139 | int main() 140 | { 141 | case1(); 142 | case2(); 143 | case3(); 144 | case4(); 145 | 146 | cout << "ranges algorithm demo" << endl; 147 | } 148 | -------------------------------------------------------------------------------- /ch4/regex.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ regex.cpp -std=c++17 -o a.out;./a.out 4 | // g++ regex.cpp -std=c++20 -o a.out;./a.out 5 | // g++ regex.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | static 14 | auto make_regex = [](const auto& txt) 15 | { 16 | return std::regex(txt); 17 | }; 18 | 19 | static 20 | auto make_match = []() 21 | { 22 | return std::smatch(); 23 | }; 24 | 25 | void case1() 26 | { 27 | using namespace std; 28 | 29 | //using sregex = std::regex; 30 | //using cregex = std::regex; 31 | 32 | using namespace std::regex_constants; 33 | regex reg1 {"xyz", icase|optimize}; 34 | regex reg2 {R"(a*b{2,3})"}; 35 | 36 | auto reg = make_regex(R"(^(\w+)\:(\w+)$)"); 37 | 38 | assert(regex_match("a:b", reg)); 39 | assert(!regex_match("a,b", reg)); 40 | 41 | auto str = "neir:automata"s; 42 | 43 | auto what = make_match(); 44 | 45 | assert(regex_match(str, what, reg)); 46 | 47 | assert(what[1] == "neir"); 48 | assert(what[2] == "automata"); 49 | 50 | for(const auto& x : what) { 51 | cout << x << ','; 52 | } 53 | cout << endl; 54 | 55 | //str = "a,b"; 56 | //assert(!regex_match(str, what, reg)); 57 | } 58 | 59 | void case2() 60 | { 61 | using namespace std; 62 | 63 | auto str = "god of war"s; 64 | 65 | auto reg = make_regex(R"((\w+)\s(\w+))"); 66 | auto what = make_match(); 67 | 68 | auto found = regex_search( 69 | str, what, reg); 70 | 71 | assert(found); 72 | assert(!what.empty()); 73 | assert(what[1] == "god"); 74 | assert(what[2] == "of"); 75 | 76 | 77 | auto reg1 = make_regex(R"(^unix)"); 78 | auto reg2 = make_regex(R"(com$)"); 79 | 80 | assert(regex_search("unix_time", reg1)); 81 | assert(regex_search("abc.com", reg2)); 82 | 83 | assert(!regex_search("win_os", reg1)); 84 | assert(!regex_search("abc.org", reg2)); 85 | } 86 | 87 | void case3() 88 | { 89 | using namespace std; 90 | 91 | auto str = "god of war"s; 92 | 93 | auto reg = make_regex(R"((\w+)\s(\w+))"); 94 | 95 | auto new_str = regex_replace( 96 | str, 97 | make_regex(R"(\w+$)"), 98 | "peace" 99 | ); 100 | 101 | cout << new_str << endl; 102 | 103 | cout << regex_replace( 104 | " xxx ", 105 | make_regex("^\\s+"), "" 106 | ) << endl; 107 | 108 | cout << regex_replace( 109 | " xxx---", 110 | make_regex("\\-+$"), "" 111 | ) << endl; 112 | 113 | cout << regex_replace( 114 | regex_replace( 115 | str, 116 | make_regex("\\w+$"), 117 | "peace" 118 | ), 119 | make_regex("^\\w+"), 120 | "godness" 121 | ) << endl; 122 | 123 | cout << regex_replace( 124 | "hello mike", 125 | make_regex(R"((\w+)\s(\w+))"), 126 | "$2-says-$1 ($&)" 127 | ) << endl; 128 | } 129 | 130 | void case4() 131 | { 132 | //auto reg = make_regex(R"(\w+)"); 133 | 134 | for (int i = 0;i < 100; i++) { 135 | auto reg = make_regex(R"(\w+)"); 136 | regex_match("123", reg); 137 | } 138 | } 139 | 140 | int main() 141 | { 142 | case1(); 143 | case2(); 144 | case3(); 145 | case4(); 146 | 147 | using namespace std; 148 | 149 | cout << "regex demo" << endl; 150 | } 151 | -------------------------------------------------------------------------------- /ch4/search.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ search.cpp -std=c++17 -o a.out;./a.out 4 | // g++ search.cpp -std=c++20 -o a.out;./a.out 5 | // g++ search.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void case1() 20 | { 21 | vector v = {3,5,1,7,10,99,42}; 22 | 23 | auto print = [](const auto& x) 24 | { 25 | cout << x << ","; 26 | }; 27 | 28 | // total sort 29 | std::sort(begin(v), end(v)); 30 | for_each(cbegin(v), cend(v), print); 31 | cout << endl; 32 | 33 | auto found = binary_search( 34 | cbegin(v), cend(v), 7 35 | ); 36 | cout << "found: " << found << endl; 37 | 38 | decltype(cend(v)) pos; 39 | 40 | pos = std::lower_bound( 41 | cbegin(v), cend(v), 7 42 | ); 43 | //assert(pos != cend(v)); 44 | //assert(*pos == 7); 45 | found = (pos != cend(v)) && (*pos == 7); 46 | assert(found); 47 | 48 | pos = std::lower_bound( 49 | cbegin(v), cend(v), 9 50 | ); 51 | //assert(pos != cend(v)); 52 | //cout << *pos << endl; 53 | found = (pos != cend(v)) && (*pos == 9); 54 | assert(!found); 55 | 56 | pos = std::upper_bound( 57 | cbegin(v), cend(v), 9 58 | ); 59 | //cout << *pos << endl; 60 | 61 | cout << "equal_range:"; 62 | #if __cplusplus >= 201703 63 | auto [lower, upper] = std::equal_range( 64 | cbegin(v), cend(v), 7 65 | ); 66 | for_each( 67 | lower, std::next(upper), print 68 | ); 69 | #else 70 | auto range = std::equal_range( 71 | cbegin(v), cend(v), 7 72 | ); 73 | //cout << *range.first << endl; 74 | //cout << *range.second << endl; 75 | for_each( 76 | range.first, std::next(range.second), print 77 | ); 78 | #endif 79 | cout << endl; 80 | } 81 | 82 | void case2() 83 | { 84 | multiset s = {3,5,1,7,7,7,10,99,42}; 85 | 86 | auto print = [](const auto& x) 87 | { 88 | cout << x << ","; 89 | }; 90 | 91 | auto pos = s.find(7); 92 | assert(pos != s.end()); 93 | 94 | auto lower_pos = s.lower_bound(7); 95 | auto upper_pos = s.upper_bound(7); 96 | 97 | for_each( 98 | lower_pos, upper_pos, print 99 | ); 100 | cout << endl; 101 | 102 | auto [p1, p2] = s.equal_range(7); 103 | for_each( 104 | p1, p2, print 105 | ); 106 | cout << endl; 107 | } 108 | 109 | void case3() 110 | { 111 | vector v = {1,9,11,3,5,7}; 112 | 113 | decltype(v.end()) pos; 114 | 115 | pos = std::find( 116 | begin(v), end(v), 3 117 | ); 118 | assert(pos != end(v)); 119 | 120 | pos = std::find_if( 121 | begin(v), end(v), 122 | [](auto x) { 123 | return x % 2 == 0; 124 | } 125 | ); 126 | assert(pos == end(v)); 127 | 128 | array arr = {3,5}; 129 | pos = std::find_first_of( 130 | begin(v), end(v), 131 | begin(arr), end(arr) 132 | ); 133 | assert(pos != end(v)); 134 | } 135 | 136 | int main() 137 | { 138 | case1(); 139 | case2(); 140 | case3(); 141 | 142 | using namespace std; 143 | 144 | cout << "search demo" << endl; 145 | } 146 | -------------------------------------------------------------------------------- /ch4/shared_ptr.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ shared_ptr.cpp -std=c++17 -o a.out;./a.out 4 | // g++ shared_ptr.cpp -std=c++20 -o a.out;./a.out 5 | // g++ shared_ptr.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | void case1() 14 | { 15 | using namespace std; 16 | 17 | shared_ptr ptr1(new int(10)); 18 | assert(*ptr1 = 10); 19 | 20 | shared_ptr ptr2(new string("hello")); 21 | assert(*ptr2 == "hello"); 22 | 23 | auto ptr3 = make_shared(42); 24 | assert(ptr3 && *ptr3 == 42); 25 | 26 | auto ptr4 = make_shared("zelda"); 27 | assert(!ptr4->empty()); 28 | } 29 | 30 | void case2() 31 | { 32 | using namespace std; 33 | 34 | auto ptr1 = make_shared(42); 35 | assert(ptr1 && ptr1.use_count() == 1 ); 36 | //assert(ptr1 && ptr1.unique() ); 37 | 38 | auto ptr2 = ptr1; 39 | assert(ptr1 && ptr2); 40 | 41 | assert(ptr1 == ptr2); 42 | assert(ptr1.use_count() == 2); 43 | assert(ptr2.use_count() == 2); 44 | } 45 | 46 | class DemoShared final 47 | { 48 | public: 49 | DemoShared() = default; 50 | ~DemoShared() 51 | { 52 | // do some blocking thing ... 53 | } 54 | }; 55 | 56 | int main() 57 | { 58 | using namespace std; 59 | 60 | case1(); 61 | case2(); 62 | 63 | cout << "smart_ptr demo" << endl; 64 | } 65 | -------------------------------------------------------------------------------- /ch4/sort.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ sort.cpp -std=c++17 -o a.out;./a.out 4 | // g++ sort.cpp -std=c++20 -o a.out;./a.out 5 | // g++ sort.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | void case1() 20 | { 21 | minstd_rand rand; 22 | 23 | vector v = {3,5,1,7,10,99,42}; 24 | 25 | auto print = [](const auto& x) 26 | { 27 | cout << x << ","; 28 | }; 29 | 30 | std::reverse(begin(v), end(v)); 31 | for_each(cbegin(v), cend(v), print); 32 | cout << endl; 33 | 34 | cout << "sorting..." << endl; 35 | 36 | // total sort 37 | std::sort(begin(v), end(v)); 38 | for_each(cbegin(v), cend(v), print); 39 | cout << endl; 40 | 41 | std::shuffle(begin(v), end(v), rand); 42 | 43 | // top3 44 | std::partial_sort( 45 | begin(v), next(begin(v), 3), end(v)); 46 | for_each(cbegin(v), cend(v), print); 47 | cout << endl; 48 | 49 | std::shuffle(begin(v), end(v), rand); 50 | 51 | // best3 52 | std::nth_element( 53 | begin(v), next(begin(v), 3), end(v)); 54 | for_each(cbegin(v), cend(v), print); 55 | cout << endl; 56 | 57 | std::shuffle(begin(v), end(v), rand); 58 | 59 | // Median 60 | auto mid_iter = 61 | next(begin(v), size(v)/2); 62 | std::nth_element( begin(v), mid_iter, end(v)); 63 | for_each(cbegin(v), cend(v), print); 64 | cout << "median is " << *mid_iter << endl; 65 | 66 | std::shuffle(begin(v), end(v), rand); 67 | 68 | // partition 69 | auto pos = std::partition( 70 | begin(v), end(v), 71 | [](const auto& x) 72 | { 73 | return x > 9; 74 | } 75 | ); 76 | for_each(begin(v), pos, print); 77 | cout << endl; 78 | for_each(cbegin(v), cend(v), print); 79 | cout << endl; 80 | 81 | // min/max 82 | auto [mi, ma] = std::minmax_element( 83 | cbegin(v), cend(v) 84 | ); 85 | cout << *mi << "," 86 | << *ma << endl; 87 | } 88 | 89 | int main() 90 | { 91 | case1(); 92 | //case2(); 93 | 94 | using namespace std; 95 | 96 | cout << "sort demo" << endl; 97 | } 98 | -------------------------------------------------------------------------------- /ch4/string.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ string.cpp -std=c++17 -o a.out;./a.out 4 | // g++ string.cpp -std=c++20 -o a.out;./a.out 5 | // g++ string.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | void case1() 14 | { 15 | using namespace std; 16 | 17 | string str = "abc"; 18 | 19 | assert(str.length() == 3); 20 | assert(str < "xyz"); 21 | assert(str.substr(0, 1) == "a"); 22 | assert(str[1] == 'b'); 23 | assert(str.find("1") == string::npos); 24 | assert(str + "d" == "abcd"); 25 | auto p = str.c_str(); 26 | cout << p << endl; 27 | 28 | #if __cplusplus > 201703 29 | assert(str.starts_with("ab")); 30 | assert(str.ends_with("c")); 31 | #endif 32 | 33 | vector v; 34 | v.push_back('a'); 35 | v.push_back('b'); 36 | assert(v.front() == 'a'); 37 | } 38 | 39 | void case2() 40 | { 41 | // enable literal suffix 's' 42 | using namespace std::literals; 43 | 44 | using std::string; 45 | 46 | auto str = "std string"s; 47 | 48 | assert(str.length() > 0); 49 | 50 | assert("time"s.size() == 4); 51 | } 52 | 53 | void case3() 54 | { 55 | using namespace std; 56 | 57 | auto str = R"(nier:automata)"; 58 | 59 | auto str1 = R"(char""'')"; 60 | auto str2 = R"(\r\n\t\")"; 61 | auto str3 = R"(\\\$)"; 62 | auto str4 = "\\\\\\$"; 63 | 64 | auto str5 = R"==(R"(xxx)")=="; 65 | 66 | cout << str1 << endl; 67 | cout << str2 << endl; 68 | cout << str3 << endl; 69 | cout << str4 << endl; 70 | cout << str5 << endl; 71 | } 72 | 73 | void case4() 74 | { 75 | using namespace std; 76 | 77 | assert(stoi("42") == 42); 78 | assert(stol("253") == 253L); 79 | assert(stod("2.0") == 2.0); 80 | 81 | assert(to_string(1984) == "1984"); 82 | } 83 | 84 | int main() 85 | { 86 | case1(); 87 | case2(); 88 | case3(); 89 | case4(); 90 | 91 | using namespace std; 92 | 93 | cout << "string demo" << endl; 94 | } 95 | -------------------------------------------------------------------------------- /ch4/string_view.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ string_view.cpp -std=c++17 -o a.out;./a.out 4 | // g++ string_view.cpp -std=c++20 -o a.out;./a.out 5 | // g++ string_view.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void case1() 15 | { 16 | using namespace std; 17 | 18 | string_view sv; 19 | assert(sv.empty()); 20 | 21 | sv = "fantasy"s; 22 | assert(sv.size() == 7); 23 | 24 | sv = "c++"; 25 | assert(sv.size() == 3); 26 | 27 | string_view sv2("std c++", 3); 28 | assert(sv2 == "std"); 29 | 30 | // enable literal suffix 'sv' 31 | using namespace std::literals; 32 | auto sv3 = "viewit"sv; 33 | } 34 | 35 | void case2() 36 | { 37 | using namespace std; 38 | using namespace std::literals; 39 | 40 | string_view sv {"god of war"s}; 41 | 42 | assert(!sv.empty()); 43 | assert(sv.size() == 10); 44 | assert(sv.front() == 'g'); 45 | assert(sv[2] == 'd'); 46 | assert(sv.find('w') != string_view::npos); 47 | 48 | #if __cplusplus > 201703 49 | assert(sv.starts_with("god")); 50 | assert(sv.ends_with("war")); 51 | #endif 52 | } 53 | 54 | void case3() 55 | { 56 | using namespace std; 57 | 58 | string_view sv {"god of war"}; 59 | 60 | assert(sv.substr(4, 2) == "of"); 61 | 62 | sv.remove_prefix(3); 63 | assert(sv == " of war"); 64 | 65 | sv.remove_suffix(4); 66 | assert(sv == " of"); 67 | } 68 | 69 | int main() 70 | { 71 | case1(); 72 | case2(); 73 | case3(); 74 | 75 | using namespace std; 76 | 77 | cout << "string_view demo" << endl; 78 | } 79 | -------------------------------------------------------------------------------- /ch4/thread.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ thread.cpp -lpthread -std=c++20 -o a.out;./a.out 4 | 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | void case1() 17 | { 18 | auto task = [](bool flag) 19 | { 20 | auto tid = this_thread::get_id(); 21 | 22 | if (flag) { 23 | cout << tid << "thread yield" << endl; 24 | this_thread::yield(); 25 | } 26 | 27 | auto time = chrono::system_clock::now() + 100ms; 28 | this_thread::sleep_until(time); 29 | 30 | cout << tid << " sleep until" << endl; 31 | }; 32 | 33 | thread t1(task, true); 34 | thread t2(task, false); 35 | 36 | t1.join(); 37 | t2.join(); 38 | } 39 | 40 | void case2() 41 | { 42 | auto task = []() 43 | { 44 | this_thread::sleep_for(1s); 45 | 46 | cout << "sleep for 1s" << endl; 47 | }; 48 | 49 | //thread t1(task); 50 | //t1.join(); 51 | 52 | jthread jt{task}; 53 | } 54 | 55 | void case3() 56 | { 57 | mutex mu1, mu2; 58 | 59 | int x = 0; 60 | if (scoped_lock guard(mu1, mu2); x == 0) { 61 | cout << "scoped_locked" << endl; 62 | } 63 | } 64 | 65 | int main() 66 | { 67 | case1(); 68 | case2(); 69 | case3(); 70 | 71 | cout << "thread demo" << endl; 72 | } 73 | -------------------------------------------------------------------------------- /ch4/thread_local.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ thread_local.cpp -lpthread -std=c++17 -o a.out;./a.out 4 | // g++ thread_local.cpp -lpthread -std=c++20 -o a.out;./a.out 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | using namespace std; 13 | 14 | void case1() 15 | { 16 | //static int n = 0; 17 | thread_local int n = 0; 18 | 19 | auto f = [&](int x) 20 | { 21 | n += x; 22 | 23 | cout << n; 24 | cout << ", tid=" << 25 | this_thread::get_id() << endl; 26 | }; 27 | 28 | thread t1(f, 10); 29 | thread t2(f, 20); 30 | 31 | t1.join(); 32 | t2.join(); 33 | } 34 | 35 | 36 | 37 | int main() 38 | { 39 | case1(); 40 | 41 | cout << "thread_local demo" << endl; 42 | } 43 | -------------------------------------------------------------------------------- /ch4/tuple.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ tuple.cpp -std=c++17 -o a.out;./a.out 4 | // g++ tuple.cpp -std=c++20 -o a.out;./a.out 5 | // g++ tuple.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | void case1() 17 | { 18 | tuple t1 {0, 1, "x"}; 19 | 20 | assert(get<0>(t1) == 0); 21 | assert(get<1>(t1) == 1); 22 | assert(get(t1) == "x"); 23 | 24 | auto t2 = make_tuple(1L, "string"s); 25 | assert(get(t2) == 1); 26 | 27 | get<1>(t2) = "hi"; 28 | assert(get<1>(t2) == "hi"); 29 | } 30 | 31 | void case2() 32 | { 33 | using Student = tuple; 34 | 35 | //struct Student { 36 | // int id; 37 | // string name; 38 | // double score; 39 | //}; 40 | 41 | auto f = []() { 42 | return make_tuple(true, "ok"s); 43 | }; 44 | 45 | auto [flag, msg] = f(); 46 | assert(flag && msg == "ok"); 47 | 48 | } 49 | 50 | int main() 51 | { 52 | case1(); 53 | case2(); 54 | 55 | cout << "tuple demo" << endl; 56 | } 57 | -------------------------------------------------------------------------------- /ch4/unique_ptr.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ unique_ptr.cpp -std=c++17 -o a.out;./a.out 4 | // g++ unique_ptr.cpp -std=c++20 -o a.out;./a.out 5 | // g++ unique_ptr.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #if 1 14 | template 15 | std::unique_ptr 16 | my_make_unique(Args&&... args) 17 | { 18 | return std::unique_ptr( 19 | new T(std::forward(args)...)); 20 | } 21 | #endif 22 | 23 | void case1() 24 | { 25 | using namespace std; 26 | 27 | unique_ptr ptr1(new int(10)); 28 | assert(*ptr1 == 10); 29 | assert(ptr1 != nullptr); 30 | 31 | unique_ptr ptr2(new string("hello")); 32 | assert(*ptr2 == "hello"); 33 | assert(ptr2->size() == 5); 34 | 35 | //ptr1++; 36 | //ptr2 += 2; 37 | 38 | //unique_ptr ptr3; 39 | //*ptr3 = 42; 40 | 41 | auto ptr3 = make_unique(42); 42 | assert(ptr3 && *ptr3 == 42); 43 | 44 | auto ptr4 = make_unique("god of war"); 45 | assert(!ptr4->empty()); 46 | 47 | auto ptr5 = my_make_unique(100L); 48 | assert(*ptr5 == 100); 49 | } 50 | 51 | void case2() 52 | { 53 | using namespace std; 54 | 55 | auto ptr1 = make_unique(42); 56 | assert(ptr1 && *ptr1 == 42); 57 | 58 | auto ptr2 = std::move(ptr1); 59 | assert(!ptr1 && ptr2); 60 | } 61 | 62 | int main() 63 | { 64 | using namespace std; 65 | 66 | case1(); 67 | case2(); 68 | 69 | cout << "unique_ptr demo" << endl; 70 | } 71 | -------------------------------------------------------------------------------- /ch4/variant.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ variant.cpp -std=c++17 -o a.out;./a.out 4 | // g++ variant.cpp -std=c++20 -o a.out;./a.out 5 | // g++ variant.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | void case1() 17 | { 18 | union { 19 | int n; 20 | float f; 21 | double d; 22 | } x; 23 | 24 | x.d = 3.14; 25 | x.n = 10; 26 | assert(x.n == 10); 27 | 28 | } 29 | 30 | void case2() 31 | { 32 | variant v; 33 | 34 | v = 42; 35 | assert(v.index() == 0); 36 | assert(get<0>(v) == 42); 37 | 38 | v = 3.14f; 39 | assert(v.index() == 1); 40 | 41 | v = 2.718; 42 | assert(v.index() == 2); 43 | 44 | auto x = get(v); 45 | cout << x << endl; 46 | 47 | auto p = get_if(&v); 48 | assert(p == nullptr); 49 | } 50 | 51 | void case3() 52 | { 53 | variant v; 54 | 55 | auto vistor = [](auto& x) { 56 | x = x + x; 57 | cout << x << endl; 58 | }; 59 | 60 | v = 10; 61 | std::visit(vistor, v); 62 | 63 | v = "ok"; 64 | std::visit(vistor, v); 65 | } 66 | 67 | void case4() 68 | { 69 | struct Swan final { 70 | void fly() { 71 | cout << "swan flies" << endl; 72 | } 73 | }; 74 | 75 | struct Ostrich final { 76 | void fly() { 77 | cout << "ostrich can't fly" << endl; 78 | } 79 | }; 80 | 81 | struct Phoenix final { 82 | void fly() { 83 | cout << "phoenix flies high" << endl; 84 | } 85 | }; 86 | 87 | variant bird; 88 | auto fly_it = [](auto& x) { 89 | x.fly(); 90 | }; 91 | 92 | bird = Swan(); 93 | std::visit(fly_it, bird); 94 | 95 | bird = Ostrich(); 96 | std::visit(fly_it, bird); 97 | } 98 | 99 | 100 | int main() 101 | { 102 | case1(); 103 | case2(); 104 | case3(); 105 | case4(); 106 | 107 | cout << "variant demo" << endl; 108 | } 109 | -------------------------------------------------------------------------------- /ch4/weak_ptr.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ weak_ptr.cpp -std=c++17 -o a.out;./a.out 4 | // g++ weak_ptr.cpp -std=c++20 -o a.out;./a.out 5 | // g++ weak_ptr.cpp -std=c++17 -I../common -o a.out;./a.out 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | class Node final 15 | { 16 | public: 17 | using this_type = Node; 18 | //using shared_type = std::shared_ptr; 19 | using shared_type = std::weak_ptr; 20 | public: 21 | shared_type next; 22 | public: 23 | Node() = default; 24 | ~Node() 25 | { 26 | using namespace std; 27 | cout << "node dtor" << endl; 28 | } 29 | }; 30 | 31 | void case1() 32 | { 33 | using namespace std; 34 | 35 | auto n1 = make_shared(); 36 | auto n2 = make_shared(); 37 | 38 | assert(n1.use_count() == 1); 39 | assert(n2.use_count() == 1); 40 | 41 | n1->next = n2; 42 | n2->next = n1; 43 | 44 | assert(n1.use_count() == 1); 45 | assert(n2.use_count() == 1); 46 | 47 | if (!n1->next.expired()) { 48 | auto ptr = n1->next.lock(); 49 | assert(ptr == n2); 50 | } 51 | 52 | //assert(n1.use_count() == 2); 53 | //assert(n2.use_count() == 2); 54 | } 55 | 56 | class SharedSelf final : 57 | public std::enable_shared_from_this 58 | { }; 59 | 60 | void case2() 61 | { 62 | using namespace std; 63 | 64 | auto ptr1 = make_shared(); 65 | assert(ptr1.use_count() == 1); 66 | 67 | auto ptr2 = ptr1->shared_from_this(); 68 | assert(ptr2.use_count() == 2); 69 | 70 | auto ptr3 = ptr1->weak_from_this(); 71 | assert(!ptr3.expired() && ptr1.use_count() == 2); 72 | } 73 | 74 | int main() 75 | { 76 | using namespace std; 77 | 78 | case1(); 79 | case2(); 80 | 81 | cout << "weak_ptr demo" << endl; 82 | } 83 | -------------------------------------------------------------------------------- /ch5/a.com.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC5DCCAcygAwIBAgIUWgj/Pf1I+gQp3mrSw1RQ2tJp4ngwDQYJKoZIhvcNAQEL 3 | BQAwEDEOMAwGA1UEAwwFYS5jb20wHhcNMjEwNDI3MDI1MjU0WhcNMzEwNDI1MDI1 4 | MjU0WjAQMQ4wDAYDVQQDDAVhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC 5 | AQoCggEBAMkj58/WEaCs+Ov84hO+mqSkv2iMKjVkJUyoRRgGWTPFh4uhoYOF8jXw 6 | Txvp6/C3uUDwNzzmM2A6bU/yz+D4nB2Y9udnj+EgVLXLbRhn0cLQCAVepaw8eZZM 7 | QADBRmr3ehyc7l5hYV3SLo61RBPzwt99v2iHuYzQWiFYcZgsD+hBy8oVRdjl2BN+ 8 | B96ynLFTw90oeJiiAxu8p0iP2XdbqEiIl08Q1Nm+/7DmSLJpV2cuOqVHEaV5+1LA 9 | /72Ens2fMj9u1YEMZHAR7QAQuv4pb7xUwWtahW27HQsTor6WdF6DkIW8sdYaQkmW 10 | 6NWeX0SkpXxrnwnKF09/vZj39cARmD0CAwEAAaM2MDQwEAYDVR0RBAkwB4IFYS5j 11 | b20wCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEB 12 | CwUAA4IBAQB4kZV75auFuS9DHiyucUv8blXw7FJNBZOLNBuMRv0kTSwx1Jug0F9x 13 | uH/KU4me2rIoIUJbr8La4CdjUy7AA5vniR1U+mu7FUb0IEOyLKHbM0o47PNpOaBw 14 | k1Lfrkv2e4TsvAjNVybGKMZb8dL+AIetRD6BVBtpHr/OUACeqJ7eq6AAZaS8bbua 15 | MMdMlGI50+ie29Ba58shdp55gAkJ8RsHo0xXw005/eIo0syMMSSleMo3teIpJ+5f 16 | r6KqBksxR8LatserNX2/fRUz0Fs1J1yJAZF7R1KWfmkdJFc9GGYdMu3LrgHTaWux 17 | /fNwrtbzBzRk9K1HkhOAYUSlkN6+NveD 18 | -----END CERTIFICATE----- 19 | -------------------------------------------------------------------------------- /ch5/a.com.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDJI+fP1hGgrPjr 3 | /OITvpqkpL9ojCo1ZCVMqEUYBlkzxYeLoaGDhfI18E8b6evwt7lA8Dc85jNgOm1P 4 | 8s/g+JwdmPbnZ4/hIFS1y20YZ9HC0AgFXqWsPHmWTEAAwUZq93ocnO5eYWFd0i6O 5 | tUQT88Lffb9oh7mM0FohWHGYLA/oQcvKFUXY5dgTfgfespyxU8PdKHiYogMbvKdI 6 | j9l3W6hIiJdPENTZvv+w5kiyaVdnLjqlRxGleftSwP+9hJ7NnzI/btWBDGRwEe0A 7 | ELr+KW+8VMFrWoVtux0LE6K+lnReg5CFvLHWGkJJlujVnl9EpKV8a58JyhdPf72Y 8 | 9/XAEZg9AgMBAAECggEAcDzC6+zOJVSgCj8wgEgJzvnHfTVJkEVzstTqyT8xo3wD 9 | 6NymXdfukj6oRjE/4TEEBMKGcEscPAQeX1Bkw2q24qUqkXHujXcXDeKX29iC6ixf 10 | bW+lDvkn98BQrpsrCiFSWIkRUkUQqePQ6v0nIeMRyNhIaLHjzjmtMZJCwOFFdxnS 11 | G2M1hTQhigLkRymyIyafihcpL7L/nRz7jF9pm0UMQ5T09C7TkCimYWvEqH3isvCS 12 | 8+iWt2d7RNXQnuVF/ltBnUcxv7foncI/SNh3e/TDhTtDoHhwu01sYvcPtdA+cf11 13 | qGIPmJqy+H4d1s4WVh3n0vK5cgzFzCQHactJODvjAQKBgQDzRz5mzhFWj7fQu7Yv 14 | UlitoposdgqOCKzAccgucQj6TfQmwYHJEO3g2wglz92wPxE9oD7nIYzP/Ovo0gQq 15 | w+gtuGJYBMIWCoT1PZlVeA7aSzy3TWTxZp3eBzTMl8VFYVPYfVQct4481phDXD4U 16 | WuqmUOSPpT+qS8hvK6RkP3udnQKBgQDTqI/FJwQBK7Uz414kVpbS9xF80rBwaVfj 17 | TSXZkl2ox7w9TZBV+v5L44DSczIDW8fEjVSXNzO6MdRSxG1O7NKybLGwf0LB8g3Z 18 | e5js8rt7URjfoJHmYXyXkNwdnki7fzI2pBGOJHP/055uq2aOj+zjn/6JvPPhB9jw 19 | VKN59OwzIQKBgBCTDQRSC8pa9koJT+s/b/08c8aNsEBnBOYDmoDXgKYVA4pUarQ5 20 | LAvCwHZbCB6G3XTWYxK6LW7KK4RsMo57VGkxA7o9cL+xrcdLkBPLny9uKs/OPQ9Z 21 | T24eDZHW0UDd1amNOFrQgqdQc4U7Vptqakw0fK3wszq1+Qzh60xNKu3dAoGAFzOT 22 | DvmH5tjztAxodXNIdTfAIv61eJ0TlUcPrxnsSmQarl2iRMqOtaLqrCcUhGm7LECR 23 | 1UGn2fE8ZRZDJTOwpP5lPAO3Pata+UwjJ1Y0VwA8ycbAN5DYJ4Upm9WOA3+d8X9q 24 | rToxvQllhJwlUdtVDF6teEvOMAy8KxwcD3JZsgECgYBumHaRzhG03b4Mr3p5rMUX 25 | m3TQv6LGBrctWucXKiKGb17cMRx9mWgiIgAezSsLvldKrGfIVNFwxIsluCqGemAs 26 | 0LeNyc4+hdzXLySrb8+YzdNBCarZLuxElHpru8Jmg2t+fIqZk9Lcg8Gka7tb6EOB 27 | Pa71KZdJi+2XPnFWpCNUVQ== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /ch5/cinatra.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // apt-get update 4 | // apt-get install libboost-system-dev -y 5 | // libboost-dev libboost-all-dev 6 | // 7 | // if you have boost 1.72, thenneed not to link boost_system 8 | // 9 | // g++ cinatra.cpp -std=c++17 -lstdc++fs -lspdlog -lssl -lcrypto -lboost_system -pthread -I../common -o a.out;./a.out& 10 | // g++ cinatra.cpp -std=c++20 -lstdc++fs -lspdlog -lssl -lcrypto -lboost_system -pthread -I../common -o a.out;./a.out& 11 | 12 | #include 13 | 14 | #if __has_include() 15 | #include 16 | #elif __has_include() 17 | #define SPDLOG_COMPILED_LIB 18 | #include 19 | #else 20 | #error "no format lib for demo" 21 | #endif 22 | 23 | #define CINATRA_ENABLE_SSL 24 | #include 25 | 26 | using namespace std; 27 | using namespace cinatra; 28 | 29 | // curl '127.1/test?a=1&b=2' 30 | void srv1() 31 | { 32 | const int max_threads = 2; 33 | 34 | http_server srv(max_threads); 35 | 36 | srv.listen("0.0.0.0", "80"); 37 | 38 | auto handler = [](auto& req, auto& res) { 39 | cout << req.raw_url() << endl; 40 | cout << "header: \n" << req.head() << endl; 41 | 42 | res.set_status(status_type::ok); 43 | res.set_content("hello http srv\n"); 44 | res.build_response_str(); 45 | 46 | //res.set_status_and_content(status_type::ok, "hello http srv"); 47 | }; 48 | 49 | srv.set_http_handler("/test", handler); 50 | 51 | srv.run(); 52 | } 53 | 54 | 55 | // curl 127.1/api 56 | // curl 127.1/api -d "abcde" -v -H "Content-type: text/plain" 57 | void srv2() 58 | { 59 | #if defined(SPDLOG_COMPILED_LIB) 60 | using namespace fmt; 61 | #endif 62 | 63 | const auto max_threads = 2; 64 | const auto addr = "0.0.0.0"s; 65 | const auto port = 80; 66 | 67 | http_server srv(max_threads); 68 | 69 | if (srv.port_in_use(port)) { 70 | cout << "port_in_use" << endl; 71 | return; 72 | } 73 | 74 | srv.set_keep_alive_timeout(30); 75 | srv.listen(addr, to_string(port)); 76 | 77 | srv.set_not_found_handler( 78 | [](auto& req, auto& res) { 79 | res.set_status_and_content( 80 | status_type::forbidden, "code:403\n"); 81 | }); 82 | 83 | srv.set_http_handler( 84 | "/api", 85 | [](auto& req, auto& res) { 86 | auto method = req.get_method(); 87 | 88 | if (method == "GET") { 89 | res.set_status_and_content( 90 | status_type::not_found, "code:404\n"); 91 | return; 92 | } 93 | 94 | assert(method == "POST"); 95 | 96 | if (!req.has_body()) { 97 | res.set_status_and_content( 98 | status_type::bad_request, "code:400\n"); 99 | return; 100 | } 101 | 102 | res.add_header("Metroid", "Prime"); 103 | 104 | //cout << "body: \n" << req.body() << endl; 105 | res.set_status_and_content( 106 | status_type::ok, 107 | format("host:{}\ndata:{}\n", 108 | req.get_header_value("host"), 109 | req.body())); 110 | }); 111 | 112 | srv.run(); 113 | } 114 | 115 | // curl 'https://127.0.0.1' -k 116 | // curl --resolve a.com:443:127.0.0.1 'https://a.com' -kv 117 | void srv3() 118 | { 119 | http_ssl_server srv(1); 120 | 121 | srv.set_ssl_conf({"./a.com.crt", "./a.com.key"}); 122 | 123 | srv.listen("0.0.0.0", "443"); 124 | 125 | srv.set_http_handler( 126 | "/", 127 | [](auto& req, auto& res) { 128 | 129 | cout << "host: " 130 | << req.get_header_value("host") << endl; 131 | 132 | res.set_status_and_content( 133 | status_type::ok, "hello https srv\n"); 134 | } 135 | ); 136 | 137 | srv.run(); 138 | } 139 | 140 | int main() 141 | { 142 | cout << "cinatra http srv demo" << endl; 143 | 144 | //srv1(); 145 | //srv2(); 146 | srv3(); 147 | } 148 | 149 | -------------------------------------------------------------------------------- /ch5/cpr.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // https://github.com/whoshuu/cpr/ 4 | // cmake . -DUSE_SYSTEM_CURL=ON -DBUILD_CPR_TESTS=OFF 5 | // make && make install 6 | // 7 | // g++ cpr.cpp -std=c++17 -lcpr -lpthread -lcurl -o a.out;./a.out 8 | // g++ cpr.cpp -std=c++20 -lcpr -lpthread -lcurl -o a.out;./a.out 9 | 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | using namespace std; 17 | 18 | void case1() 19 | { 20 | //const auto url = "http://nginx.org"s; 21 | const auto url = "http://openresty.org"s; 22 | 23 | auto res = cpr::Get( 24 | cpr::Url{url} 25 | ); 26 | 27 | cout << res.elapsed << endl; 28 | 29 | cout << res.url << endl; 30 | cout << res.status_code << endl; 31 | //cout << res.header["server"] << endl; 32 | cout << res.text.length() << endl; 33 | 34 | for(auto& [k,v] : res.header) { 35 | cout << k << "=>" 36 | << v << endl; 37 | } 38 | cout << endl; 39 | } 40 | 41 | void case2() 42 | { 43 | //const auto url = "http://www.163.com"s; 44 | const auto url = "http://openresty.org"s; 45 | 46 | auto res1 = cpr::Head( 47 | cpr::Url{url} 48 | ); 49 | assert(res1.text.empty()); 50 | 51 | auto res2 = cpr::Get( 52 | cpr::Url{url}, 53 | cpr::Parameters{ 54 | {"a", "1"}, {"b", "2"}} 55 | ); 56 | 57 | auto res3 = cpr::Post( 58 | cpr::Url{url}, 59 | cpr::Header{{"x", "xxx"},{"expect",""}}, 60 | cpr::Body{"post data"}, 61 | cpr::Timeout{200ms} 62 | ); 63 | } 64 | 65 | void case3() 66 | { 67 | auto f = cpr::GetAsync( 68 | cpr::Url{"http://openresty.org"} 69 | ); 70 | 71 | auto res = f.get(); 72 | 73 | cout << res.elapsed << endl; 74 | 75 | for(auto& [k,v] : res.header) { 76 | cout << k << "=>" 77 | << v << endl; 78 | } 79 | } 80 | 81 | int main() 82 | { 83 | case1(); 84 | case2(); 85 | case3(); 86 | 87 | cout << "libcpr demo" << endl; 88 | } 89 | -------------------------------------------------------------------------------- /ch5/curl.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // sudo apt-get remove libcurl4 4 | // sudo apt-get install libcurl4-openssl-dev 5 | // 6 | // g++ curl.cpp -std=c++17 -lcurl -o a.out;./a.out 7 | // g++ curl.cpp -std=c++20 -lcurl -o a.out;./a.out 8 | // 9 | // curl-config --libs 10 | // curl-config --version 11 | // curl-config --features 12 | // curl-config --protocols 13 | 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | 20 | using namespace std; 21 | 22 | // in curl.h 23 | size_t write_callback(char* ptr, size_t size, size_t nmemb, void* userdata); 24 | 25 | void case1() 26 | { 27 | auto curl = curl_easy_init(); 28 | assert(curl); 29 | 30 | curl_easy_setopt(curl, CURLOPT_URL, "http://nginx.org"); 31 | 32 | auto res = curl_easy_perform(curl); 33 | if (res != CURLE_OK) { 34 | cout << curl_easy_strerror(res) << endl; 35 | } 36 | 37 | curl_easy_cleanup(curl); 38 | } 39 | 40 | void case2() 41 | { 42 | //using curl_t = CURL; 43 | 44 | auto curl = curl_easy_init(); 45 | 46 | if (!curl) { 47 | cout << "curl init error" << endl; 48 | return; 49 | } 50 | 51 | curl_easy_setopt(curl, CURLOPT_URL, "http://nginx.org"); 52 | 53 | //curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL); 54 | 55 | #if 0 56 | decltype(&write_callback) f = 57 | [](char *ptr, size_t size, size_t nmemb, void *userdata) 58 | { 59 | cout << "size = " << size * nmemb << endl; 60 | return size * nmemb; 61 | }; 62 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, f); 63 | #endif 64 | 65 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, 66 | (decltype(&write_callback)) 67 | [](char *ptr, size_t size, size_t nmemb, void *userdata) 68 | { 69 | cout << "size = " << size * nmemb << endl; 70 | return size * nmemb; 71 | } 72 | ); 73 | 74 | auto res = curl_easy_perform(curl); 75 | 76 | if (res != CURLE_OK) { 77 | cout << curl_easy_strerror(res) << endl; 78 | } 79 | 80 | curl_easy_cleanup(curl); 81 | } 82 | 83 | int main() 84 | { 85 | curl_global_init(CURL_GLOBAL_SSL); 86 | 87 | //case1(); 88 | case2(); 89 | 90 | cout << curl_version() << endl; 91 | cout << "libcurl demo" << endl; 92 | 93 | curl_global_cleanup(); 94 | } 95 | -------------------------------------------------------------------------------- /ch5/demo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import pydemo 4 | 5 | pydemo.info() 6 | 7 | x = pydemo.add(1,2) 8 | print(x) 9 | 10 | s = pydemo.use_str("hello c++") 11 | print(s) 12 | 13 | t = pydemo.use_tuple((1,2, "matrix")) 14 | print(t) 15 | 16 | v = pydemo.use_list([1,2,3]) 17 | print(v) 18 | 19 | p = pydemo.Point(999) 20 | print(p.get()) 21 | 22 | p.set(1984) 23 | assert(p.get() == 1984) 24 | -------------------------------------------------------------------------------- /ch5/embedded.lua: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/luajit 2 | 3 | -- copyright (c) 2020 chrono 4 | 5 | print('hello c++') 6 | 7 | print(collectgarbage("count")) 8 | 9 | print(os.time()) 10 | print(os.date("%Y-%m-%d")) 11 | 12 | print(jit.version .. ' on ' ..jit.os) 13 | 14 | -------------------------------------------------------------------------------- /ch5/gperf.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // sudo cp src/pprof /usr/bin 4 | // 5 | // pprof --text ./a.out case1.perf > case1.txt 6 | // pprof --pdf ./a.out case1.perf >case1.pdf 7 | // pprof --svg ./a.out case1.perf >case1.svg 8 | // pprof --collapsed ./a.out case1.perf > case1.cbt 9 | // 10 | // ./flamegraph.pl case1.cbt > flame.svg 11 | // ./flamegraph.pl --invert --color aqua case1.cbt > icicle.svg 12 | // 13 | // g++ gperf.cpp -std=c++17 -lprofiler -ltcmalloc -g -O0 -o a.out;./a.out 14 | // g++ gperf.cpp -std=c++20 -lprofiler -ltcmalloc -g -O0 -o a.out;./a.out 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | using namespace std; 27 | 28 | auto make_cpu_profiler = 29 | [](const string& filename) 30 | { 31 | ProfilerStart(filename.c_str()); 32 | ProfilerRegisterThread(); 33 | 34 | return std::shared_ptr( 35 | nullptr, 36 | [](void*){ 37 | ProfilerStop(); 38 | } 39 | ); 40 | }; 41 | 42 | static 43 | auto make_regex = [](const auto& txt) 44 | { 45 | return std::regex(txt); 46 | }; 47 | 48 | static 49 | auto make_match = []() 50 | { 51 | return std::smatch(); 52 | }; 53 | 54 | void case1() 55 | { 56 | auto cp = make_cpu_profiler("case1.perf"); 57 | 58 | auto str = "neir:automata"s; 59 | 60 | #if 0 61 | auto reg = make_regex(R"(^(\w+)\:(\w+)$)"); 62 | auto what = make_match(); 63 | #endif 64 | 65 | for(int i = 0; i < 1000; i++) { 66 | 67 | #if 1 68 | auto reg = make_regex(R"(^(\w+)\:(\w+)$)"); 69 | auto what = make_match(); 70 | #endif 71 | 72 | assert(regex_match(str, what, reg)); 73 | } 74 | } 75 | 76 | 77 | int main() 78 | { 79 | case1(); 80 | 81 | cout << "gperf demo" << endl; 82 | } 83 | -------------------------------------------------------------------------------- /ch5/json.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // git clone git@github.com:nlohmann/json.git 4 | // wget https://github.com/nlohmann/json/releases/download/v3.7.3/json.hpp 5 | // 6 | // g++ json.cpp -std=c++17 -I../common -o a.out;./a.out 7 | // g++ json.cpp -std=c++20 -I../common -o a.out;./a.out 8 | 9 | #include 10 | 11 | // you should put json.hpp in ../common 12 | #include "json.hpp" 13 | 14 | using namespace std; 15 | 16 | using json_t = nlohmann::json; 17 | 18 | void case1() 19 | { 20 | json_t j; 21 | j["age"] = 23; 22 | j["name"] = "spiderman"; 23 | j["gear"]["suits"] = "2099"; 24 | j["jobs"] = {"superhero", "neighborhood"}; 25 | 26 | vector v = {1,2,3}; 27 | j["numbers"] = v; 28 | 29 | map m = {{"one",1}, {"two", 2}}; 30 | j["kv"] = m; 31 | 32 | cout << j.dump() << endl; 33 | cout << j.dump(2) << endl; 34 | 35 | #if 0 36 | json_t j = { 37 | {"age", 23}, 38 | {"name", "spiderman"}, 39 | {"jobs", {"superhero", "neighborhood"}}, 40 | {"gear", {"suits", "2099"}} 41 | }; 42 | 43 | cout << j.dump(2) << endl; 44 | #endif 45 | } 46 | 47 | void case2() 48 | { 49 | string str = R"({ 50 | "name": "peter", 51 | "age" : 23, 52 | "married" : true 53 | })"; 54 | 55 | auto j = json_t::parse(str); 56 | 57 | assert(j["age"] == 23); 58 | assert(j["name"] == "peter"); 59 | 60 | cout << j.dump(2) << endl; 61 | } 62 | 63 | void case3() 64 | { 65 | auto txt = "bad:data"s; 66 | 67 | try 68 | { 69 | auto j = json_t::parse(txt); 70 | } 71 | catch(std::exception& e) 72 | { 73 | cout << e.what() << endl; 74 | } 75 | } 76 | 77 | void case4() 78 | { 79 | auto j = R"({ 80 | "os": "linux", 81 | "arch": "arm64" 82 | })"_json; 83 | 84 | assert(j["os"] == "linux"); 85 | assert(j["arch"] == "arm64"); 86 | 87 | cout << j.dump(2) << endl; 88 | } 89 | 90 | void case5() 91 | { 92 | auto j = R"({"n":[0,1,2]})"_json; 93 | 94 | auto data = json_t::to_bson(j); 95 | auto obj = json_t::from_bson(data); 96 | 97 | assert(obj["n"][0] == 0); 98 | } 99 | 100 | int main() 101 | { 102 | //cout << json_t::meta() << endl; 103 | cout << json_t::meta().dump(2) << endl; 104 | 105 | case1(); 106 | case2(); 107 | case3(); 108 | case4(); 109 | case5(); 110 | 111 | cout << "json demo" << endl; 112 | } 113 | -------------------------------------------------------------------------------- /ch5/lexical_cast.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ lexical_cast.cpp -std=c++17 -o a.out;./a.out 4 | // g++ lexical_cast.cpp -std=c++20 -o a.out;./a.out 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | using namespace std; 14 | using namespace boost; 15 | 16 | void case1() 17 | { 18 | auto n1 = lexical_cast("42"); 19 | auto n2 = lexical_cast("100"); 20 | auto n3 = lexical_cast("64000", 2); 21 | 22 | auto f1 = lexical_cast("1.414"); 23 | auto f2 = lexical_cast("2.718"); 24 | 25 | assert(n1 == 42); 26 | assert(n2 == 100); 27 | assert(n3 == 64); 28 | 29 | auto x = stol("99L"); 30 | assert(x == 99L); 31 | } 32 | 33 | void case2() 34 | { 35 | auto s1 = lexical_cast(42); 36 | auto s2 = lexical_cast(0x64); 37 | auto s3 = lexical_cast(0.618); 38 | 39 | assert(s1 == "42"); 40 | assert(s2 == "100"); 41 | //assert(s3 == "0.618"); 42 | //cout << s3 << endl; 43 | 44 | assert(to_string(0x64) == "100"); 45 | } 46 | 47 | void case3() 48 | { 49 | try 50 | { 51 | lexical_cast("-100"); 52 | lexical_cast("1024L"); 53 | lexical_cast("999LL"); 54 | } 55 | catch(bad_lexical_cast& e) 56 | { 57 | cout << e.what() << endl; 58 | } 59 | 60 | 61 | //cout << stol("-100") << endl; 62 | //cout << stol("1024L") << endl; 63 | //cout << stoll("999LL") << endl; 64 | 65 | assert(stoi("-100") == -100); 66 | assert(stol("1024L") == 1024L); 67 | assert(stoll("999LL") == 999LL); 68 | } 69 | 70 | template 71 | T std_lexical_cast(const U& arg) 72 | { 73 | if constexpr (std::is_same_v) { 74 | return std::stoi(arg); 75 | } 76 | 77 | if constexpr (std::is_same_v) { 78 | return std::stol(arg); 79 | } 80 | 81 | if constexpr (std::is_same_v) { 82 | return std::stoll(arg); 83 | } 84 | 85 | if constexpr (std::is_same_v) { 86 | return std::stod(arg); 87 | } 88 | 89 | if constexpr (std::is_same_v) { 90 | return std::to_string(arg); 91 | } 92 | 93 | return T {}; 94 | } 95 | 96 | void case4() 97 | { 98 | assert(std_lexical_cast("+42") == 42); 99 | assert(std_lexical_cast("100L") == 100); 100 | std_lexical_cast("0.618"); 101 | 102 | assert(std_lexical_cast(999) == "999"); 103 | } 104 | 105 | int main() 106 | { 107 | case1(); 108 | case2(); 109 | case3(); 110 | case4(); 111 | 112 | cout << "lexical_cast demo" << endl; 113 | } 114 | -------------------------------------------------------------------------------- /ch5/lua_shared.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ lua_shared.cpp -std=c++17 -shared -fPIC -o liblua_shared.so 4 | // g++ lua_shared.cpp -std=c++20 -shared -fPIC -o liblua_shared.so 5 | 6 | //#include 7 | 8 | extern "C" { 9 | 10 | int num = 10; 11 | int my_add(int a, int b); 12 | 13 | } 14 | 15 | int my_add(int a, int b) 16 | { 17 | return a + b; 18 | } 19 | -------------------------------------------------------------------------------- /ch5/luajit.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // git clone git@github.com:openresty/luajit2.git 4 | // make && make install 5 | // 6 | // git clone git@github.com:vinniefalco/LuaBridge.git 7 | // 8 | // g++ luajit.cpp -std=c++17 -I../common -I/usr/local/include/luajit-2.1 -lluajit-5.1 -ldl -o a.out;./a.out 9 | // g++ luajit.cpp -std=c++17 -I../common -I/usr/local/include/luajit-2.1 -lluajit-5.1 -ldl -O0 -g -o a.out 10 | // 11 | // g++ luajit.cpp -std=c++17 -I/usr/local/include/luajit-2.1 /usr/local/lib/libluajit-5.1.a -ldl -o a.out;./a.out 12 | // g++ luajit.cpp -std=c++17 -I/usr/local/include/luajit-2.1 -L/usr/local/lib -Wl,-rpath,/usr/local/lib -lluajit-5.1 -ldl -o a.out;./a.out 13 | // 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | extern "C" { 20 | #include 21 | #include 22 | #include 23 | } 24 | 25 | #include 26 | //namespace lua = luabridge; 27 | using namespace luabridge; 28 | 29 | using namespace std; 30 | 31 | //using MyLuaState = std::shared_ptr; 32 | auto make_luavm = []() 33 | { 34 | std::shared_ptr vm( 35 | luaL_newstate(), lua_close 36 | ); 37 | assert(vm); 38 | 39 | luaL_openlibs(vm.get()); 40 | 41 | return vm; 42 | }; 43 | 44 | #define L vm.get() 45 | 46 | void case1() 47 | { 48 | //MyLuaState L; 49 | auto vm = make_luavm(); 50 | 51 | auto package = getGlobal(L, "package"); 52 | 53 | string path = package["path"]; 54 | string cpath = package["cpath"]; 55 | 56 | cout << path << endl; 57 | cout << cpath << endl; 58 | } 59 | 60 | void case2() 61 | { 62 | //MyLuaState L; 63 | auto vm = make_luavm(); 64 | 65 | int status; 66 | 67 | status = luaL_dostring(L, "print('hello lua')"); 68 | status = luaL_dofile(L, "./embedded.lua"); 69 | status = luaL_dofile(L, "./shared.lua"); 70 | 71 | //L.dofile("./embedded.lua"); 72 | } 73 | 74 | void case3() 75 | { 76 | //MyLuaState L; 77 | auto vm = make_luavm(); 78 | 79 | int status; 80 | string chunk = R"( 81 | function say(s) 82 | print(s) 83 | end 84 | function add(a, b) 85 | return a + b 86 | end 87 | )"; 88 | 89 | status = luaL_dostring(L, chunk.c_str()); 90 | assert(status == 0); 91 | 92 | auto f1 = getGlobal(L, "say"); 93 | f1("say something"); 94 | 95 | auto f2 = getGlobal(L, "add"); 96 | auto v = f2(10, 20); 97 | assert(v == 30); 98 | //cout << v << endl; 99 | 100 | //L.dofile("./embedded.lua"); 101 | } 102 | 103 | int main() 104 | { 105 | case1(); 106 | case2(); 107 | case3(); 108 | 109 | cout << "luajit demo" << endl; 110 | } 111 | -------------------------------------------------------------------------------- /ch5/msgpack.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // sudo apt-get install libmsgpack-dev 4 | // 5 | // /usr/include/msgpack 6 | // 7 | // g++ msgpack.cpp -std=c++17 -o a.out;./a.out 8 | // g++ msgpack.cpp -std=c++20 -o a.out;./a.out 9 | // 10 | // source include 11 | // g++ msgpack.cpp -std=c++17 -I../common/include -o a.out;./a.out 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | #if MSGPACK_VERSION_MAJOR < 2 21 | # error "msgpack is too old." 22 | #endif 23 | 24 | using namespace std; 25 | 26 | void case1() 27 | { 28 | auto serialize = [](const auto& x) { 29 | msgpack::sbuffer sbuf; 30 | msgpack::pack(sbuf, x); 31 | 32 | cout << sbuf.size() << endl; 33 | }; 34 | 35 | serialize(99); 36 | serialize(3.14); 37 | serialize("hello msgpack"s); 38 | serialize(vector{1,2,3}); 39 | serialize(tuple{1,"str"s, true}); 40 | } 41 | 42 | void case2() 43 | { 44 | vector v = {1,2,3,4,5}; 45 | 46 | msgpack::sbuffer sbuf; 47 | msgpack::pack(sbuf, v); 48 | 49 | cout << sbuf.size() << endl; 50 | 51 | auto handle = msgpack::unpack(sbuf.data(), sbuf.size()); 52 | auto obj = handle.get(); 53 | cout << obj << endl; 54 | 55 | //decltype(v) v2; 56 | vector v2; 57 | obj.convert(v2); 58 | 59 | assert(std::equal(begin(v), end(v), begin(v2))); 60 | } 61 | 62 | void case3() 63 | { 64 | msgpack::sbuffer sbuf; 65 | //msgpack::packer packer(sbuf); 66 | msgpack::packer packer(sbuf); 67 | 68 | packer.pack(10).pack("monado"s) 69 | .pack(vector{1,2,3}); 70 | 71 | cout << sbuf.size() << endl; 72 | 73 | for(decltype(sbuf.size()) offset = 0; 74 | offset != sbuf.size();){ 75 | 76 | auto handle = msgpack::unpack( 77 | sbuf.data(), sbuf.size(), offset); 78 | auto obj = handle.get(); 79 | cout << obj << endl; 80 | } 81 | 82 | #if 0 83 | cout << "lambda " << endl; 84 | for(decltype(sbuf.size()) offset = 0; 85 | offset != sbuf.size();){ 86 | 87 | auto handle = msgpack::unpack( 88 | sbuf.data(), sbuf.size(), offset, 89 | 90 | [](auto type, auto len, auto data) 91 | { 92 | cout << type << ":" << len << endl; 93 | return true; 94 | } 95 | 96 | ); 97 | } 98 | #endif 99 | } 100 | 101 | class Book final 102 | { 103 | public: 104 | int id; 105 | string title; 106 | set tags; 107 | public: 108 | MSGPACK_DEFINE(id, title, tags); 109 | }; 110 | 111 | void case4() 112 | { 113 | Book book1 = {1, "1984", {"a","b"}}; 114 | 115 | msgpack::sbuffer sbuf; 116 | msgpack::pack(sbuf, book1); 117 | 118 | // may cause std::bad_cast error 119 | //auto obj = msgpack::unpack(sbuf.data(), sbuf.size()).get(); 120 | 121 | auto handle = msgpack::unpack(sbuf.data(), sbuf.size()); 122 | auto obj = handle.get(); 123 | 124 | Book book2; 125 | obj.convert(book2); 126 | //msgpack::unpack(sbuf.data(), sbuf.size()).get().convert(book2); 127 | 128 | 129 | assert(book2.id == book1.id); 130 | assert(book2.tags.size() == 2); 131 | cout << book2.title << endl; 132 | } 133 | 134 | void case5() 135 | { 136 | auto txt = ""s; 137 | 138 | try 139 | { 140 | auto handle = msgpack::unpack( 141 | txt.data(), txt.size()); 142 | } 143 | catch(std::exception& e) 144 | { 145 | cout << e.what() << endl; 146 | } 147 | } 148 | 149 | int main() 150 | { 151 | case1(); 152 | case2(); 153 | case3(); 154 | case4(); 155 | case5(); 156 | 157 | cout << msgpack_version() << endl; 158 | cout << "msgpack demo" << endl; 159 | } 160 | -------------------------------------------------------------------------------- /ch5/protobuf.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // sudo apt-get install protobuf-compiler 4 | // sudo apt-get install libprotobuf-dev 5 | // sudo apt-get install libprotoc-dev 6 | // 7 | // protoc --cpp_out=. sample.proto 8 | // 9 | // g++ protobuf.cpp -std=c++17 -lprotobuf -lpthread -o a.out;./a.out 10 | // g++ protobuf.cpp -std=c++20 -lprotobuf -lpthread -o a.out;./a.out 11 | 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | // uncomment this to enable proto2 18 | //#define PROTO2 2 19 | 20 | // just for convient 21 | //#include "sample.pb.h" 22 | #include "sample.pb.cc" 23 | 24 | using namespace std; 25 | 26 | void case1() 27 | { 28 | using vendor_t = sample::Vendor; 29 | 30 | vendor_t v; 31 | 32 | #if PROTO2 33 | assert(!v.IsInitialized()); 34 | #endif 35 | 36 | v.set_id(1); 37 | v.set_name("sony"); 38 | v.set_valid(true); 39 | v.clear_tel(); 40 | 41 | assert(v.IsInitialized()); 42 | #if PROTO2 43 | assert(v.has_id() && v.id() == 1); 44 | assert(v.has_name() && v.name() == "sony"); 45 | assert(v.has_valid() && v.valid()); 46 | #endif 47 | 48 | cout << v.DebugString() << endl; 49 | 50 | string enc; 51 | v.SerializeToString(&enc); 52 | 53 | vendor_t v2; 54 | 55 | #if PROTO2 56 | assert(!v2.IsInitialized()); 57 | #endif 58 | 59 | v2.ParseFromString(enc); 60 | 61 | assert(v.id() == v2.id()); 62 | } 63 | 64 | void case2() 65 | { 66 | auto alloc_vendor = []() 67 | { 68 | return new sample::Vendor; 69 | }; 70 | 71 | auto v = alloc_vendor(); 72 | 73 | v->set_id(1); 74 | v->set_name("sony"); 75 | v->set_valid(true); 76 | assert(v->IsInitialized()); 77 | 78 | using product_t = sample::Product; 79 | 80 | product_t p; 81 | 82 | p.set_id(1); 83 | p.set_name("walkman"); 84 | 85 | assert(p.tag_size() == 0); 86 | p.add_tag("fashion"); 87 | p.add_tag("type_record"); 88 | 89 | #if PROTO2 90 | assert(!p.has_vendor()); 91 | #endif 92 | 93 | p.set_allocated_vendor(v); 94 | } 95 | 96 | int main() 97 | { 98 | //GOOGLE_PROTOBUF_VERIFY_VERSION; 99 | 100 | case1(); 101 | case2(); 102 | 103 | cout << "protobuf demo" << endl; 104 | } 105 | -------------------------------------------------------------------------------- /ch5/ptree.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ ptree.cpp -std=c++17 -o a.out;./a.out 4 | // g++ ptree.cpp -std=c++20 -o a.out;./a.out 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | using namespace boost::property_tree; 15 | 16 | inline namespace detail{ 17 | 18 | auto conf_str = R"({ 19 | "enable" : true, 20 | "env" : "test", 21 | "timeout" : 10, 22 | "secret" : { 23 | "crt" : "ccc", 24 | "key" : "kkk" 25 | }, 26 | "uri" : ["a", "b", "c"] 27 | })"; 28 | 29 | stringstream conf_stream{conf_str}; 30 | } 31 | 32 | void case1() 33 | { 34 | ptree pt; 35 | 36 | read_json(conf_stream, pt); 37 | 38 | cout << pt.get("enable") << endl; 39 | cout << pt.get("env") << endl; 40 | cout << pt.get("timeout") << endl; 41 | 42 | cout << pt.get("secret.crt") << endl; 43 | cout << pt.get("secret.key") << endl; 44 | 45 | for(auto& [i, x] : pt.get_child("uri")) { 46 | cout << x.data() << endl; 47 | } 48 | } 49 | 50 | int main() 51 | { 52 | case1(); 53 | 54 | cout << "property_tree demo" << endl; 55 | } 56 | -------------------------------------------------------------------------------- /ch5/pybind.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // apt install python3-pip 4 | // pip3 install pybind11 5 | // 6 | // apt install python3-dev 7 | // mkdir build && cd build 8 | // cmake .. -DPYBIND11_TEST=OFF 9 | // 10 | // g++ pybind.cpp -std=c++17 -shared -fPIC `python3 -m pybind11 --includes` -o pydemo`python3-config --extension-suffix` 11 | // g++ pybind.cpp -std=c++20 -shared -fPIC `python3 -m pybind11 --includes` -o pydemo`python3-config --extension-suffix` 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | using namespace std; 19 | 20 | namespace py = pybind11; 21 | 22 | class Point final 23 | { 24 | private: 25 | int x = 0; 26 | public: 27 | Point() = default; 28 | ~Point() = default; 29 | 30 | Point(int a) : x(a) {} 31 | public: 32 | int get() const 33 | { 34 | return x; 35 | } 36 | 37 | void set(int a) 38 | { 39 | x = a; 40 | } 41 | }; 42 | 43 | PYBIND11_MODULE(pydemo, m) 44 | { 45 | m.doc() = "pybind11 demo doc"; 46 | 47 | m.def("info", 48 | []() 49 | { 50 | //cout << "c++ version = " << __cplusplus << endl; 51 | //cout << "gcc version = " << __VERSION__ << endl; 52 | //cout << "libstdc++ = " << __GLIBCXX__ << endl; 53 | py::print("c++ version =", __cplusplus); 54 | py::print("gcc version =", __VERSION__); 55 | py::print("libstdc++ =", __GLIBCXX__); 56 | } 57 | ); 58 | 59 | m.def("add", 60 | [](int a, int b) 61 | { 62 | return a + b; 63 | } 64 | ); 65 | 66 | m.def("use_str", 67 | [](const string& str) 68 | { 69 | //cout << str << endl; 70 | py::print(str); 71 | return str + "!!"; 72 | } 73 | ); 74 | 75 | m.def("use_tuple", 76 | [](tuple x) 77 | { 78 | get<0>(x)++; 79 | get<1>(x)++; 80 | get<2>(x)+= "??"; 81 | 82 | return x; 83 | } 84 | ); 85 | 86 | m.def("use_list", 87 | [](const vector& v) 88 | { 89 | auto vv = v; 90 | 91 | //for(auto& x : vv) { 92 | // //cout << x << ","; 93 | //} 94 | //cout << endl; 95 | py::print("input :", vv); 96 | 97 | vv.push_back(100); 98 | 99 | return vv; 100 | } 101 | ); 102 | 103 | py::class_(m, "Point") 104 | .def(py::init()) 105 | .def(py::init()) 106 | .def("get", &Point::get) 107 | .def("set", &Point::set) 108 | ; 109 | } 110 | 111 | #if 0 112 | void info() 113 | { 114 | cout << "c++ version = " << __cplusplus << endl; 115 | cout << "gcc version = " << __VERSION__ << endl; 116 | cout << "libstdc++ = " << __GLIBCXX__ << endl; 117 | } 118 | 119 | int add(int a, int b) 120 | { 121 | return a + b; 122 | } 123 | 124 | PYBIND11_MODULE(pydemo, m) 125 | { 126 | m.doc() = "pybind11 demodoc"; 127 | 128 | m.def("info", &info, "cpp info"); 129 | m.def("add", &add, "add func"); 130 | } 131 | #endif 132 | 133 | #if 0 134 | 135 | int main() 136 | { 137 | cout << "pybind demo" << endl; 138 | } 139 | #endif 140 | -------------------------------------------------------------------------------- /ch5/sample.proto: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 by Chrono 2 | // 3 | // protoc --cpp_out=. sample_v3.proto 4 | 5 | syntax = "proto3"; 6 | 7 | package sample; 8 | 9 | message Vendor 10 | { 11 | uint32 id = 1; 12 | string name = 2; 13 | bool valid = 3; 14 | string tel = 4; 15 | } 16 | 17 | message Product 18 | { 19 | int32 id = 1; 20 | string name = 2; 21 | 22 | repeated string tag = 3; 23 | 24 | Vendor vendor = 10; 25 | } 26 | -------------------------------------------------------------------------------- /ch5/sample.proto.v2: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // protoc --cpp_out=. sample.proto 4 | 5 | syntax = "proto2"; 6 | 7 | package sample; 8 | 9 | message Vendor 10 | { 11 | required uint32 id = 1; 12 | required string name = 2; 13 | required bool valid = 3; 14 | optional string tel = 4; 15 | } 16 | 17 | message Product 18 | { 19 | required int32 id = 1; 20 | required string name = 2; 21 | 22 | repeated string tag = 3; 23 | 24 | optional Vendor vendor = 10; 25 | } 26 | -------------------------------------------------------------------------------- /ch5/sample.proto.v3: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 by Chrono 2 | // 3 | // protoc --cpp_out=. sample_v3.proto 4 | 5 | syntax = "proto3"; 6 | 7 | package sample; 8 | 9 | message Vendor 10 | { 11 | uint32 id = 1; 12 | string name = 2; 13 | bool valid = 3; 14 | string tel = 4; 15 | } 16 | 17 | message Product 18 | { 19 | int32 id = 1; 20 | string name = 2; 21 | 22 | repeated string tag = 3; 23 | 24 | Vendor vendor = 10; 25 | } 26 | -------------------------------------------------------------------------------- /ch5/shared.lua: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/luajit 2 | 3 | -- copyright (c) 2021 chrono 4 | 5 | local ffi = require "ffi" 6 | 7 | local ffi_load = ffi.load 8 | local ffi_null = ffi.null 9 | local ffi_cdef = ffi.cdef 10 | local ffi_typeof = ffi.typeof 11 | local ffi_new = ffi.new 12 | local ffi_C = ffi.C 13 | 14 | ffi_cdef[[ 15 | int num; 16 | int my_add(int a, int b); 17 | ]] 18 | 19 | print(jit.version) 20 | print(jit.os) 21 | print(jit.arch) 22 | print(jit.status()) 23 | 24 | local shared = ffi_load("./liblua_shared.so") 25 | 26 | print(shared.num) 27 | 28 | local x = shared.my_add(1, 2) 29 | print(x) 30 | -------------------------------------------------------------------------------- /ch5/string_algo.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ string_algo.cpp -std=c++17 -o a.out;./a.out 4 | // g++ string_algo.cpp -std=c++20 -o a.out;./a.out 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | using namespace std; 17 | using namespace boost; 18 | 19 | void case1() 20 | { 21 | auto str = "hello c++"s; 22 | 23 | assert(starts_with(str, "he")); 24 | assert(ends_with(str, "c++")); 25 | assert(!ends_with(str, "C++")); 26 | assert(contains(str, "llo")); 27 | 28 | auto ustr = to_upper_copy(str); 29 | assert(ustr == "HELLO C++"); 30 | assert(iends_with(str, "c++")); 31 | assert(icontains(ustr, "llo")); 32 | assert(iequals(str, ustr)); 33 | 34 | auto tstr = trim_copy_if( 35 | str, [](auto& c) { 36 | return c == '+'; 37 | }); 38 | assert(tstr == "hello c"); 39 | 40 | trim_right_if(str, [](auto& c) { 41 | return c < 'l'; 42 | }); 43 | assert(str == "hello"); 44 | //cout << str << endl; 45 | } 46 | 47 | void case2() 48 | { 49 | auto str = "apple google facebook"s; 50 | 51 | replace_head(str, 3, "App"); 52 | cout << str << endl; 53 | 54 | replace_tail(str, 4, "cook"); 55 | cout << str << endl; 56 | 57 | replace_first(str, "oo", "xx"); 58 | cout << str << endl; 59 | 60 | ireplace_all(str, "LE", "GE"); 61 | cout << str << endl; 62 | 63 | ireplace_nth(str, "ge", 1, "MM"); 64 | cout << str << endl; 65 | } 66 | 67 | void case3() 68 | { 69 | auto str = "123,456,999, 1024"; 70 | 71 | //vector res; 72 | //unordered_set res; 73 | set res; 74 | 75 | res = split(res, str, 76 | [](const auto& c) { 77 | return c == ',' || c == ' '; 78 | }, token_compress_on); 79 | 80 | for(auto&& x: res) { 81 | cout << '[' << x << "]"; 82 | } 83 | cout << endl; 84 | } 85 | 86 | void case4() 87 | { 88 | vector v = {"apple", "pear", "tomato"}; 89 | 90 | cout << join(v, "**") << endl; 91 | 92 | cout << join_if(v, "++", 93 | [](auto& x) { 94 | return std::size(x) >= 5; 95 | }) << endl; 96 | } 97 | 98 | int main() 99 | { 100 | case1(); 101 | case2(); 102 | case3(); 103 | case4(); 104 | 105 | cout << "string_algo demo" << endl; 106 | } 107 | -------------------------------------------------------------------------------- /ch5/timer.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ timer.cpp -std=c++17 -lboost_timer -o a.out;./a.out 4 | // g++ timer.cpp -std=c++20 -lboost_timer -o a.out;./a.out 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | using namespace std; 14 | using namespace boost::timer; 15 | 16 | void case1() 17 | { 18 | cpu_timer t; 19 | 20 | for (int i = 0; i < 3; i++) { 21 | t.start(); 22 | this_thread::sleep_for(100ms); 23 | 24 | t.stop(); 25 | this_thread::sleep_for(50ms); 26 | assert(t.is_stopped()); 27 | t.resume(); 28 | 29 | cout << t.format() << endl; 30 | } 31 | } 32 | 33 | void case2() 34 | { 35 | cpu_timer t; 36 | 37 | this_thread::sleep_for(1ms); 38 | 39 | auto x = t.elapsed(); 40 | 41 | cout << "wall: " << x.wall/1000 << endl; 42 | cout << "user: " << x.user << endl; 43 | cout << "sys: " << x.system << endl; 44 | } 45 | 46 | int main() 47 | { 48 | case1(); 49 | case2(); 50 | 51 | cout << "timer demo" << endl; 52 | } 53 | -------------------------------------------------------------------------------- /ch5/zmq.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // sudo apt-get install libzmq3-dev 4 | // 5 | // g++ zmq.cpp -std=c++17 -lzmq -lpthread -o a.out;./a.out 6 | // g++ zmq.cpp -std=c++20 -lzmq -lpthread -o a.out;./a.out 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | using namespace std; 17 | 18 | const auto thread_num = 1; 19 | 20 | zmq::context_t context(thread_num); 21 | 22 | auto make_sock = [&](auto mode) 23 | { 24 | return zmq::socket_t(context, mode); 25 | }; 26 | 27 | void case1() 28 | { 29 | const auto addr = "ipc:///dev/shm/zmq.sock"s; 30 | //const auto addr = "inproc:///dev/shm/zmq.sock"s; 31 | 32 | auto receiver = [=]() 33 | { 34 | auto sock = make_sock(ZMQ_PULL); 35 | 36 | sock.bind(addr); 37 | assert(sock.connected()); 38 | 39 | zmq::message_t msg; 40 | 41 | sock.recv(&msg); 42 | 43 | cout << msg.size() << endl; 44 | 45 | string s = {msg.data(), msg.size()}; 46 | cout << s << endl; 47 | }; 48 | 49 | auto sender = [=]() 50 | { 51 | auto sock = make_sock(ZMQ_PUSH); 52 | 53 | sock.connect(addr); 54 | assert(sock.connected()); 55 | 56 | string s = "hello zmq"; 57 | //zmq::message_t msg(begin(s), end(s)); 58 | //sock.send(msg); 59 | 60 | sock.send(s.data(), s.size()); 61 | }; 62 | 63 | sender(); 64 | receiver(); 65 | } 66 | 67 | void case2() 68 | { 69 | const auto addr = "tcp://127.0.0.1:5555"s; 70 | 71 | auto srv = [=]() 72 | { 73 | auto sock = make_sock(ZMQ_PULL); 74 | 75 | sock.setsockopt(ZMQ_LINGER, 0); 76 | sock.setsockopt(ZMQ_RCVHWM, 1000); 77 | 78 | sock.bind(addr); 79 | assert(sock.connected()); 80 | 81 | zmq::message_t msg; 82 | 83 | for(int i = 0; i < 4; i++) { 84 | sock.recv(&msg); 85 | 86 | string s = {msg.data(), msg.size()}; 87 | cout << s << endl; 88 | } 89 | }; 90 | 91 | auto client = [=](int i) 92 | { 93 | auto sock = make_sock(ZMQ_PUSH); 94 | 95 | sock.setsockopt(ZMQ_SNDHWM, 100); 96 | 97 | sock.connect(addr); 98 | assert(sock.connected()); 99 | 100 | string s = "zmq msg " + to_string(i); 101 | //zmq::message_t msg(begin(s), end(s)); 102 | //sock.send(msg); 103 | 104 | //sock.send(begin(s), end(s)); 105 | sock.send(s.data(), s.size()); 106 | }; 107 | 108 | auto f = std::async(srv); 109 | 110 | for(int i = 0; i < 4; i++) { 111 | client(i); 112 | } 113 | 114 | f.wait(); 115 | } 116 | 117 | int main() 118 | { 119 | auto [a, b, c] = zmq::version(); 120 | 121 | cout << "version = " 122 | << a << b << c << endl; 123 | 124 | case1(); 125 | case2(); 126 | 127 | cout << "zmq demo" << endl; 128 | } 129 | -------------------------------------------------------------------------------- /ch7/Config.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | 3 | #ifndef _CONFIG_HPP 4 | #define _CONFIG_HPP 5 | 6 | #include "cpplang.hpp" 7 | 8 | extern "C" { 9 | #include 10 | #include 11 | #include 12 | } 13 | 14 | #include 15 | 16 | BEGIN_NAMESPACE(cpp_note) 17 | 18 | class Config final 19 | { 20 | public: 21 | using vm_type = std::shared_ptr; 22 | using value_type = luabridge::LuaRef; 23 | 24 | using string_type = std::string; 25 | using string_view_type = const std::string&; 26 | using regex_type = std::regex; 27 | using match_type = std::smatch; 28 | public: 29 | Config() noexcept 30 | { 31 | assert(m_vm); 32 | 33 | luaL_openlibs(m_vm.get()); 34 | } 35 | 36 | ~Config() = default; 37 | public: 38 | void load(string_view_type filename) const 39 | { 40 | auto status = luaL_dofile(m_vm.get(), filename.c_str()); 41 | 42 | if (status != 0) { 43 | throw std::runtime_error("failed to parse config"); 44 | } 45 | } 46 | 47 | template 48 | T get(string_view_type key) const 49 | { 50 | if (!std::regex_match(key, m_what, m_reg)) { 51 | throw std::runtime_error("config key error"); 52 | } 53 | 54 | auto w1 = m_what[1].str(); 55 | auto w2 = m_what[2].str(); 56 | 57 | using namespace luabridge; 58 | 59 | auto v = getGlobal( 60 | m_vm.get(), w1.c_str()); 61 | 62 | return LuaRef_cast(v[w2]); 63 | } 64 | private: 65 | vm_type m_vm {luaL_newstate(), lua_close}; 66 | 67 | const regex_type m_reg {R"(^(\w+)\.(\w+)$)"}; 68 | mutable match_type m_what; 69 | }; 70 | 71 | END_NAMESPACE(cpp_note) 72 | 73 | #endif //_CONFIG_HPP 74 | 75 | -------------------------------------------------------------------------------- /ch7/SalesData.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | 3 | #ifndef _SALES_DATA_HPP 4 | #define _SALES_DATA_HPP 5 | 6 | #include "cpplang.hpp" 7 | 8 | #include 9 | 10 | #if MSGPACK_VERSION_MAJOR < 2 11 | # error "msgpack is too old" 12 | #endif 13 | 14 | BEGIN_NAMESPACE(cpp_note) 15 | 16 | // demo oop in C++ 17 | class SalesData final 18 | { 19 | public: 20 | using this_type = SalesData; 21 | 22 | public: 23 | using string_type = std::string; 24 | using string_view_type = const std::string&; 25 | using uint_type = unsigned int; 26 | using currency_type = double; 27 | 28 | STATIC_ASSERT(sizeof(uint_type) >= 4); 29 | STATIC_ASSERT(sizeof(currency_type) >= 4); 30 | public: 31 | SalesData(string_view_type id, uint_type s, currency_type r) noexcept 32 | : m_id(id), m_sold(s), m_revenue(r) 33 | {} 34 | 35 | SalesData(string_view_type id) noexcept 36 | : SalesData(id, 0, 0) 37 | {} 38 | 39 | public: 40 | SalesData() = default; 41 | ~SalesData() = default; 42 | 43 | SalesData(const this_type&) = default; 44 | SalesData& operator=(const this_type&) = default; 45 | 46 | SalesData(this_type&& s) = default; 47 | SalesData& operator=(this_type&& s) = default; 48 | 49 | private: 50 | string_type m_id = ""; 51 | uint_type m_sold = 0; 52 | uint_type m_revenue = 0; 53 | 54 | public: 55 | MSGPACK_DEFINE(m_id, m_sold, m_revenue); 56 | 57 | msgpack::sbuffer pack() const 58 | { 59 | msgpack::sbuffer sbuf; 60 | msgpack::pack(sbuf, *this); 61 | 62 | return sbuf; 63 | } 64 | 65 | SalesData(const msgpack::sbuffer& sbuf) 66 | { 67 | auto obj = msgpack::unpack( 68 | sbuf.data(), sbuf.size()).get(); 69 | obj.convert(*this); 70 | } 71 | 72 | public: 73 | void inc_sold(uint_type s) noexcept 74 | { 75 | m_sold += s; 76 | } 77 | 78 | void inc_revenue(currency_type r) noexcept 79 | { 80 | m_revenue += r; 81 | } 82 | public: 83 | string_view_type id() const noexcept 84 | { 85 | return m_id; 86 | } 87 | 88 | uint_type sold() const noexcept 89 | { 90 | return m_sold; 91 | } 92 | 93 | currency_type revenue() const noexcept 94 | { 95 | return m_revenue; 96 | } 97 | 98 | CPP_DEPRECATED 99 | currency_type average() const 100 | { 101 | return m_revenue / m_sold; 102 | } 103 | }; 104 | 105 | END_NAMESPACE(cpp_note) 106 | 107 | #endif //_SALES_DATA_HPP 108 | 109 | -------------------------------------------------------------------------------- /ch7/SpinLock.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | 3 | #ifndef _SPIN_LOCK_HPP 4 | #define _SPIN_LOCK_HPP 5 | 6 | #include "cpplang.hpp" 7 | 8 | BEGIN_NAMESPACE(cpp_note) 9 | 10 | // atomic spinlock with TAS 11 | class SpinLock final 12 | { 13 | public: 14 | using this_type = SpinLock; 15 | using atomic_type = std::atomic_flag; 16 | 17 | public: 18 | SpinLock() = default; 19 | ~SpinLock() = default; 20 | 21 | SpinLock(const this_type&) = delete; 22 | SpinLock& operator=(const this_type&) = delete; 23 | public: 24 | void lock() noexcept 25 | { 26 | for(;;) { 27 | if (!m_lock.test_and_set()) { 28 | return; 29 | } 30 | 31 | std::this_thread::yield(); 32 | } 33 | } 34 | 35 | bool try_lock() noexcept 36 | { 37 | return !m_lock.test_and_set(); 38 | } 39 | 40 | void unlock() noexcept 41 | { 42 | m_lock.clear(); 43 | } 44 | private: 45 | atomic_type m_lock {false}; 46 | }; 47 | 48 | // RAII for lock 49 | // you can change it to a template class 50 | class SpinLockGuard final 51 | { 52 | public: 53 | using this_type = SpinLockGuard; 54 | using spin_lock_type = SpinLock; 55 | public: 56 | SpinLockGuard(spin_lock_type& lock) noexcept 57 | : m_lock(lock) 58 | { 59 | m_lock.lock(); 60 | } 61 | 62 | ~SpinLockGuard() noexcept 63 | { 64 | m_lock.unlock(); 65 | } 66 | 67 | public: 68 | SpinLockGuard(const this_type&) = delete; 69 | SpinLockGuard& operator=(const this_type&) = delete; 70 | private: 71 | spin_lock_type& m_lock; 72 | }; 73 | 74 | 75 | END_NAMESPACE(cpp_note) 76 | 77 | #endif //_SPIN_LOCK_HPP 78 | 79 | -------------------------------------------------------------------------------- /ch7/Summary.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | 3 | #ifndef _SUMMARY_HPP 4 | #define _SUMMARY_HPP 5 | 6 | #include "cpplang.hpp" 7 | 8 | #if __cplusplus > 201703L 9 | #include 10 | #endif 11 | 12 | #include "SalesData.hpp" 13 | #include "SpinLock.hpp" 14 | 15 | BEGIN_NAMESPACE(cpp_note) 16 | 17 | class Summary final 18 | { 19 | public: 20 | using this_type = Summary; 21 | public: 22 | using sales_type = SalesData; 23 | using lock_type = SpinLock; 24 | using lock_guard_type = SpinLockGuard; 25 | 26 | using string_type = std::string; 27 | using map_type = 28 | std::map; 29 | //std::unordered_map; 30 | using minmax_sales_type = 31 | std::pair; 32 | public: 33 | Summary() = default; 34 | ~Summary() = default; 35 | 36 | Summary(const this_type&) = delete; 37 | Summary& operator=(const this_type&) = delete; 38 | private: 39 | mutable lock_type m_lock; 40 | map_type m_sales; 41 | public: 42 | void add_sales(const sales_type& s) 43 | { 44 | lock_guard_type guard(m_lock); 45 | 46 | const auto& id = s.id(); 47 | 48 | // not found 49 | if (m_sales.find(id) == m_sales.end()) { 50 | m_sales[id] = s; 51 | return; 52 | } 53 | 54 | // found 55 | // you could use iter to optimize it 56 | m_sales[id].inc_sold(s.sold()); 57 | m_sales[id].inc_revenue(s.revenue()); 58 | } 59 | 60 | minmax_sales_type minmax_sales() const 61 | { 62 | lock_guard_type guard(m_lock); 63 | 64 | if (m_sales.empty()) { 65 | return {}; 66 | } 67 | 68 | // algorithm 69 | #if __cplusplus <= 201703L 70 | auto ret = std::minmax_element( 71 | std::begin(m_sales), std::end(m_sales), 72 | [](const auto& a, const auto& b) 73 | { 74 | return a.second.sold() < b.second.sold(); 75 | }); 76 | 77 | // min max 78 | auto min_pos = std::get<0>(ret); //ret.first; 79 | auto max_pos = std::get<1>(ret); //ret.second; 80 | 81 | #else 82 | auto [min_pos, max_pos] = 83 | std::ranges::minmax_element( 84 | m_sales, {}, 85 | [](const auto& x) { 86 | return x.second.sold(); 87 | }); 88 | #endif 89 | 90 | return {min_pos->second.id(), max_pos->second.id()}; 91 | } 92 | }; 93 | 94 | END_NAMESPACE(cpp_note) 95 | 96 | #endif //_SUMMARY_HPP 97 | 98 | -------------------------------------------------------------------------------- /ch7/Zmq.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | 3 | #ifndef _ZMQ_HPP 4 | #define _ZMQ_HPP 5 | 6 | #include "cpplang.hpp" 7 | 8 | // /usr/include/zmq.hpp 9 | #include 10 | 11 | BEGIN_NAMESPACE(cpp_note) 12 | 13 | using zmq_context_type = zmq::context_t; 14 | using zmq_socket_type = zmq::socket_t; 15 | using zmq_message_type = zmq::message_t; 16 | 17 | template 18 | class ZmqContext final 19 | { 20 | #if 0 21 | public: 22 | using zmq_context_type = zmq::context_t; 23 | using zmq_socket_type = zmq::socket_t; 24 | using zmq_message_type = zmq::message_t; 25 | #endif 26 | public: 27 | ZmqContext() = default; 28 | ~ZmqContext() = default; 29 | public: 30 | inline static 31 | zmq_context_type context{thread_num}; 32 | //static 33 | //zmq_context_type& context() 34 | //{ 35 | // static zmq_context_type ctx(thread_num); 36 | // return ctx; 37 | //} 38 | public: 39 | static 40 | zmq_socket_type recv_sock(int hwm = 1000, int linger = 10) 41 | { 42 | zmq_socket_type sock(context, ZMQ_PULL); 43 | 44 | sock.setsockopt(ZMQ_RCVHWM, hwm); 45 | sock.setsockopt(ZMQ_LINGER, linger); // wait for 10ms 46 | 47 | return sock; 48 | } 49 | 50 | static 51 | zmq_socket_type send_sock(int hwm = 1000, int linger = 10) 52 | { 53 | zmq_socket_type sock(context, ZMQ_PUSH); 54 | 55 | sock.setsockopt(ZMQ_SNDHWM, hwm); 56 | sock.setsockopt(ZMQ_LINGER, linger); // wait for 10ms 57 | 58 | return sock; 59 | } 60 | }; 61 | 62 | END_NAMESPACE(cpp_note) 63 | 64 | #endif //_ZMQ_HPP 65 | 66 | -------------------------------------------------------------------------------- /ch7/backend.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // apt-get update 4 | // apt-get install libboost-system-dev -y 5 | // libboost-dev libboost-all-dev 6 | // 7 | // if you have boost 1.72, thenneed not to link boost_system 8 | // 9 | // g++ backend.cpp -std=c++17 -lstdc++fs -lboost_system -pthread -I../common -o b.out;./b.out& 10 | // g++ backend.cpp -std=c++20 -lstdc++fs -lboost_system -pthread -I../common -o b.out;./b.out& 11 | // 12 | // curl 127.1/cpp_note?token=cpp -d 'abcd' -H 'content-type: text/plain' 13 | 14 | #include 15 | 16 | #include 17 | 18 | using namespace std; 19 | using namespace cinatra; 20 | 21 | int main() 22 | { 23 | cout << "http srv is running" << endl; 24 | 25 | http_server srv(1); 26 | 27 | srv.listen("0.0.0.0", "80"); 28 | 29 | srv.set_not_found_handler( 30 | [](auto& req, auto& res) { 31 | res.set_status_and_content( 32 | status_type::forbidden, "code:403\n"); 33 | }); 34 | 35 | srv.set_http_handler( 36 | "/cpp_note", 37 | [](auto& req, auto& res) { 38 | auto token = req.get_query_value("token"); 39 | 40 | if (token != "cpp" || 41 | !req.has_body()) { 42 | res.set_status_and_content( 43 | status_type::forbidden, "code:403\n"); 44 | return; 45 | } 46 | 47 | cout << req.body() << endl; 48 | 49 | res.set_status_and_content( 50 | status_type::ok, "ok"); 51 | }); 52 | 53 | srv.run(); 54 | } 55 | -------------------------------------------------------------------------------- /ch7/cli.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ cli.cpp -std=c++17 -I../common -lzmq -lpthread -o c.out;./c.out 4 | // g++ cli.cpp -std=c++17 -I../common -lzmq -lpthread -g -O0 -o c.out 5 | // g++ cli.cpp -std=c++17 -I../common -lzmq -lpthread -g -O0 -o c.out;./c.out 6 | 7 | //#include 8 | 9 | #include "cpplang.hpp" 10 | #include "SalesData.hpp" 11 | #include "Zmq.hpp" 12 | 13 | // you should put json.hpp in ../common 14 | #include "json.hpp" 15 | 16 | USING_NAMESPACE(std); 17 | USING_NAMESPACE(cpp_note); 18 | 19 | static 20 | auto debug_print = [](auto& b) 21 | { 22 | using json_t = nlohmann::json; 23 | 24 | json_t j; 25 | 26 | j["id"] = b.id(); 27 | j["sold"] = b.sold(); 28 | j["revenue"] = b.revenue(); 29 | //j["average"] = b.average(); 30 | 31 | std::cout << j.dump(2) << std::endl; 32 | }; 33 | 34 | // sales data 35 | static 36 | auto make_sales = [=](const auto& id, auto s, auto r) 37 | //-> msgpack::sbuffer 38 | { 39 | return SalesData(id, s, r).pack(); 40 | 41 | #if 0 42 | SalesData book(id); 43 | 44 | book.inc_sold(s); 45 | book.inc_revenue(r); 46 | 47 | debug_print(book); 48 | 49 | auto buf = book.pack(); 50 | cout << buf.size() << endl; 51 | 52 | //SalesData book2 {buf}; 53 | //assert(book.id() == book2.id()); 54 | //debug_print(book2); 55 | 56 | return buf; 57 | #endif 58 | }; 59 | 60 | // zmq send 61 | static 62 | auto send_sales = [](const auto& addr, const auto& buf) 63 | { 64 | using zmq_ctx = ZmqContext<1>; 65 | 66 | auto sock = zmq_ctx::send_sock(); 67 | 68 | sock.connect(addr); 69 | assert(sock.connected()); 70 | 71 | auto len = sock.send(buf.data(), buf.size()); 72 | assert(len == buf.size()); 73 | 74 | cout << "send len = " << len << endl; 75 | }; 76 | 77 | int main() 78 | try 79 | { 80 | cout << "hello zmq client" << endl; 81 | 82 | //auto buf = make_sales("001", 10, 100); 83 | //send_sales("tcp://127.0.0.1:5555", buf); 84 | 85 | send_sales("tcp://127.0.0.1:5555", 86 | make_sales("001", 10, 100)); 87 | 88 | std::this_thread::sleep_for(100ms); 89 | 90 | send_sales("tcp://127.0.0.1:5555", 91 | make_sales("002", 20, 200)); 92 | 93 | } 94 | catch(std::exception& e) 95 | { 96 | std::cerr << e.what() << std::endl; 97 | } 98 | -------------------------------------------------------------------------------- /ch7/conf.lua: -------------------------------------------------------------------------------- 1 | -- copyright (c) 2021 chrono 2 | 3 | -- lua is more flexible than json 4 | -- you can use comment/expression 5 | -- and more lua pragram 6 | 7 | config = { 8 | 9 | -- should be same as client 10 | -- you could change it to ipc 11 | zmq_ipc_addr = "tcp://127.0.0.1:5555", 12 | 13 | http_addr = "http://localhost/cpp_note?token=cpp", 14 | 15 | time_interval = 5, -- seconds 16 | 17 | keyword = "super", 18 | 19 | sold_criteria = 100, 20 | 21 | revenue_criteria = 1000, 22 | 23 | best_n = 3, 24 | 25 | max_buf_size = 4 * 1024, 26 | 27 | } 28 | 29 | -- more config 30 | others = { 31 | -- add more 32 | } 33 | 34 | -- debug: luajit conf.lua 35 | 36 | --print(config.http_addr) 37 | -------------------------------------------------------------------------------- /ch7/cpplang.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | 3 | #ifndef _CPP_LANG_HPP 4 | #define _CPP_LANG_HPP 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | //never 'using namespace std;' in c++ header 25 | 26 | // must be C++17 or later 27 | #if __cplusplus < 201703 28 | # error "C++ is too old" 29 | #endif // __cplusplus < 201703 30 | 31 | // [[deprecated]] 32 | #if __cplusplus >= 201402 33 | # define CPP_DEPRECATED [[deprecated]] 34 | #else 35 | # define CPP_DEPRECATED [[gnu::deprecated]] 36 | #endif // __cplusplus >= 201402 37 | 38 | // static_assert 39 | #if __cpp_static_assert >= 201411 40 | # define STATIC_ASSERT(x) static_assert(x) 41 | #else 42 | # define STATIC_ASSERT(x) static_assert(x, #x) 43 | #endif 44 | 45 | // macro for convienient namespace 46 | #define BEGIN_NAMESPACE(x) namespace x { 47 | #define END_NAMESPACE(x) } 48 | #define USING_NAMESPACE(x) using namespace x 49 | 50 | //static_assert( 51 | // __GNUC__ >= 4, "GCC is too old"); 52 | 53 | #endif //_CPP_LANG_HPP 54 | 55 | -------------------------------------------------------------------------------- /ch7/srv.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | // 3 | // g++ srv.cpp -std=c++17 -I../common -I/usr/local/include/luajit-2.1 -lluajit-5.1 -ldl -lzmq -lpthread -lcpr -lcurl -o a.out;./a.out 4 | // g++ srv.cpp -std=c++17 -I../common -I/usr/local/include/luajit-2.1 -lluajit-5.1 -ldl -lzmq -lpthread -lcpr -lcurl -g -O0 -o a.out 5 | // g++ srv.cpp -std=c++17 -I../common -I/usr/local/include/luajit-2.1 -lluajit-5.1 -ldl -lzmq -lpthread -lcpr -lcurl -g -O0 -o a.out;./a.out 6 | 7 | //#include 8 | 9 | #include "cpplang.hpp" 10 | #include "Summary.hpp" 11 | #include "Zmq.hpp" 12 | #include "Config.hpp" 13 | 14 | // you should put json.hpp in ../common 15 | #include "json.hpp" 16 | 17 | #include 18 | #include 19 | 20 | USING_NAMESPACE(std); 21 | USING_NAMESPACE(cpp_note); 22 | 23 | static 24 | auto debug_print = [](auto& b) 25 | { 26 | using json_t = nlohmann::json; 27 | 28 | json_t j; 29 | 30 | j["id"] = b.id(); 31 | j["sold"] = b.sold(); 32 | j["revenue"] = b.revenue(); 33 | //j["average"] = b.average(); 34 | 35 | std::cout << j.dump(2) << std::endl; 36 | }; 37 | 38 | int main() 39 | try 40 | { 41 | cout << "hello zmq server" << endl; 42 | 43 | Config conf; 44 | conf.load("./conf.lua"); 45 | 46 | Summary sum; 47 | std::atomic_int count {0}; 48 | 49 | // todo: try-catch 50 | auto recv_cycle = [&]() 51 | { 52 | using zmq_ctx = ZmqContext<1>; 53 | 54 | // zmq recv 55 | 56 | auto sock = zmq_ctx::recv_sock(); 57 | 58 | sock.bind(conf.get("config.zmq_ipc_addr")); 59 | assert(sock.connected()); 60 | 61 | for(;;) { 62 | 63 | // xxx : shared_ptr/unique_ptr 64 | auto msg_ptr = std::make_shared(); 65 | 66 | sock.recv(msg_ptr.get()); 67 | //cout << msg_ptr->size() << endl; 68 | 69 | ++count; 70 | cout << count << endl; 71 | //printf("count = %d\n", static_cast(count)); 72 | 73 | // async process msg 74 | 75 | // todo: try-catch 76 | //auto f = std::async(std::launch::async, 77 | std::thread( 78 | [&sum, msg_ptr]() 79 | //[&sum, &count](decltype(msg_ptr) ptr) 80 | { 81 | //cout << ptr.unique() << endl; 82 | 83 | SalesData book; 84 | 85 | // xxx: json/msgpack/protobuf 86 | auto handle = msgpack::unpack( 87 | msg_ptr->data(), msg_ptr->size()); 88 | 89 | auto obj = handle.get(); 90 | obj.convert(book); 91 | 92 | //cout << book.id() << endl; 93 | //debug_print(book); 94 | 95 | sum.add_sales(book); 96 | }).detach(); // async 97 | } // for(;;) 98 | }; // recv_cycle lambda 99 | 100 | auto log_cycle = [&]() 101 | { 102 | auto http_addr = conf.get("config.http_addr"); 103 | auto time_interval = conf.get("config.time_interval"); 104 | 105 | for(;;) { 106 | std::this_thread::sleep_for(time_interval * 1s); 107 | //cout << "log_cycle" << endl; 108 | 109 | //auto info = sum.minmax_sales(); 110 | //cout << "log_cycle get info" << endl; 111 | 112 | using json_t = nlohmann::json; 113 | 114 | json_t j; 115 | 116 | j["count"] = static_cast(count); 117 | j["minmax"] = sum.minmax_sales();//{info.first, info.second}; 118 | 119 | auto res = cpr::Post( 120 | cpr::Url{http_addr}, 121 | cpr::Header{{"Content-type", "text/plain"}}, 122 | cpr::Body{j.dump()}, 123 | cpr::Timeout{200ms} 124 | ); 125 | 126 | if (res.status_code != 200) { 127 | cerr << "http post failed: " << http_addr << endl; 128 | //printf("http post failed\n"); 129 | } 130 | } // for(;;) 131 | }; // log_cycle lambda 132 | 133 | // launch log_cycle 134 | auto fu1 = std::async(std::launch::async, log_cycle); 135 | 136 | // launch recv_cycle then wait 137 | auto fu2 = std::async(std::launch::async, recv_cycle); 138 | 139 | fu2.wait(); 140 | } 141 | catch(std::exception& e) 142 | { 143 | std::cerr << e.what() << std::endl; 144 | } 145 | -------------------------------------------------------------------------------- /common/std.hpp: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 by Chrono 2 | 3 | #ifndef _COMMON_STD_HPP 4 | #define _COMMON_STD_HPP 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | //never 'using namespace std;' in c++ header 18 | 19 | #endif //_COMMON_STD_HPP 20 | 21 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # Dockerfile 2 | # chrono@2021-03 3 | 4 | # curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun 5 | # sudo service docker start 6 | # sudo usermod -aG docker ${USER} 7 | 8 | # docker build -f docker/Dockerfile -t chronolaw/cpp_note . 9 | # docker build -f docker/Dockerfile -t chronolaw/cpp_note:gcc7 . 10 | # docker build -f docker/Dockerfile -t chronolaw/cpp_note:gcc10 . 11 | 12 | # docker build -t chronolaw/cpp_note . 13 | 14 | # SRC_IMAGE=gcc:7 docker build -t chronolaw/cpp_note:gcc7 . 15 | # SRC_IMAGE=gcc:10 docker build -t chronolaw/cpp_note:gcc10 . 16 | 17 | # docker run -it --rm chronolaw/cpp_note 18 | 19 | ARG SRC_IMAGE="chronolaw/cpp_base:gcc7" 20 | #ARG SRC_IMAGE="chronolaw/cpp_base:gcc10" 21 | 22 | FROM ${SRC_IMAGE} 23 | 24 | #WORKDIR /root 25 | WORKDIR /root/cpp_note 26 | 27 | COPY setup.sh /tmp 28 | 29 | #COPY env ./cpp_note/env 30 | #COPY common ./cpp_note/common 31 | #COPY docker/setup.sh /tmp 32 | 33 | RUN /tmp/setup.sh 34 | 35 | CMD ["/bin/bash"] 36 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # chrono 2021-03 2 | # 3 | # docker-compose run --rm cpp_note 4 | # 5 | # docker ps 6 | # docker exec -it xxx bash 7 | 8 | version: "3" 9 | 10 | services: 11 | 12 | cpp_note: 13 | 14 | image: chronolaw/cpp_note 15 | 16 | container_name: cpp_note 17 | 18 | working_dir: /root/cpp_note 19 | 20 | stdin_open: true 21 | tty: true 22 | 23 | command: /bin/bash 24 | 25 | -------------------------------------------------------------------------------- /docker/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # chrono @ 2021-04 4 | 5 | # apt-get 6 | #DEBIAN_FRONTEND=noninteractive apt-get update 7 | #DEBIAN_FRONTEND=noninteractive apt-get install -y \ 8 | # vim cmake gdb pstack strace \ 9 | # libmsgpack-dev protobuf-compiler libprotobuf-dev libprotoc-dev \ 10 | # libcurl4-openssl-dev libzmq3-dev \ 11 | # python3-dev python3-pip \ 12 | # google-perftools libgoogle-perftools-dev 13 | # 14 | #DEBIAN_FRONTEND=noninteractive apt-get autoremove -y 15 | # 16 | ## python3 pybind11 17 | #pip3 install pybind11 18 | #exit 19 | 20 | #WORKDIR='/root/' 21 | #HOME='/root' 22 | 23 | #REPO='cpp_study' 24 | REPO='cpp_note' 25 | 26 | cd ${HOME} 27 | 28 | # git source code 29 | git clone https://github.com/chronolaw/${REPO} --depth=1 30 | #git clone git@github.com:chronolaw/${REPO}.git --depth=1 31 | 32 | # setup env 33 | cp ~/${REPO}/env/vimrc ~/.vimrc 34 | cp ~/${REPO}/env/bashrc ~/.bashrc 35 | cp ~/${REPO}/env/gitconfig ~/.gitconfig 36 | 37 | # source 38 | 39 | #JSON_VERSION="3.9.1" 40 | #SPDLOG_VERSION="1.8.5" 41 | #CPR_VERSION="1.4.0" 42 | #LUAJIT_VERSION="2.1-20201229" 43 | LUABRIDAGE_VERSION="2.6" 44 | #GPERF_VERSION="2.9.1" 45 | 46 | #echo ${JSON_VERSION} 47 | #echo ${HOME} 48 | 49 | #mkdir ~/github 50 | #cd ~/github 51 | 52 | # test 53 | #exit 54 | 55 | # json 56 | #curl -fsL https://github.com/nlohmann/json/releases/download/v${JSON_VERSION}/json.hpp -o json.hpp 57 | ln -s ~/github/json.hpp ~/${REPO}/common/ 58 | 59 | # spdlog && fmtlib 60 | #curl -fsL https://github.com/gabime/spdlog/archive/v${SPDLOG_VERSION}.tar.gz -o spdlog.tgz 61 | #tar xfz spdlog.tgz 62 | #cd spdlog-${SPDLOG_VERSION} 63 | #mkdir build && cd build 64 | #cmake .. && make -j && make install && make clean 65 | #cd .. 66 | 67 | # curl/cpr 68 | #curl -fsL https://github.com/whoshuu/cpr/archive/${CPR_VERSION}.tar.gz -o cpr.tgz 69 | #tar xfz cpr.tgz 70 | #cd cpr-${CPR_VERSION} 71 | #cmake . -DUSE_SYSTEM_CURL=ON -DBUILD_CPR_TESTS=OFF 72 | #make && make install && make clean 73 | #cd .. 74 | 75 | # cinatra 76 | #git clone https://github.com/qicosmos/cinatra --depth=1 77 | #git clone git@github.com:qicosmos/cinatra.git --depth=1 78 | ln -s ~/github/cinatra/include/cinatra ~/${REPO}/common/cinatra 79 | ln -s ~/github/cinatra/include/cinatra.hpp ~/${REPO}/common/ 80 | 81 | # luajit 82 | #curl -fsL https://github.com/openresty/luajit2/archive/v${LUAJIT_VERSION}.tar.gz -o luajit.tgz 83 | #tar xfz luajit.tgz 84 | #cd luajit2-${LUAJIT_VERSION} 85 | #make && make install && make clean 86 | #ln -s /usr/local/lib/libluajit-5.1.so.2 /lib/x86_64-linux-gnu/ 87 | #cd .. 88 | 89 | # luabridge 90 | #curl -fsL https://github.com/vinniefalco/LuaBridge/archive/${LUABRIDAGE_VERSION}.tar.gz -o LuaBridge.tgz 91 | #tar xfz LuaBridge.tgz 92 | ln -s ~/github/LuaBridge-${LUABRIDAGE_VERSION}/Source/LuaBridge/ ~/${REPO}/common/ 93 | 94 | # gperftools 95 | #curl -fsL https://github.com/gperftools/gperftools/releases/download/gperftools-${GPERF_VERSION}/gperftools-${GPERF_VERSION}.tar.gz -o gperf.tgz 96 | #tar xfz gperf.tgz 97 | #ln -s ~/github/gperftools-${GPERF_VERSION}/pprof-symbolize /bin/pprof 98 | 99 | # flame graph 100 | #git clone https://github.com/brendangregg/FlameGraph.git --depth=1 101 | #git clone git@github.com:brendangregg/FlameGraph.git --depth=1 102 | #ln -s ~/github/FlameGraph/flamegraph.pl /usr/local/bin/flamegraph.pl 103 | 104 | # clean 105 | #rm *.tgz 106 | 107 | -------------------------------------------------------------------------------- /env/bashrc: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 by Chrono 2 | 3 | set -o vi 4 | alias ll='ls -l' 5 | alias l='ls -lh' 6 | alias vi='vim' 7 | 8 | function set-title() { 9 | if [[ -z "$ORIG" ]]; then 10 | ORIG=$PS1 11 | fi 12 | TITLE="\[\e]2;$*\a\]" 13 | PS1=${ORIG}${TITLE} 14 | } 15 | -------------------------------------------------------------------------------- /env/gitconfig: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 by Chrono 2 | 3 | [alias] 4 | st = status 5 | ci = commit 6 | br = branch 7 | co = checkout 8 | df = diff 9 | au = add -u . 10 | ll = log --oneline --graph 11 | lg = log --graph 12 | d = difftool 13 | pop = stash pop 14 | [core] 15 | editor = vim 16 | [color] 17 | ui = true 18 | [diff] 19 | tool = vimdiff 20 | [user] 21 | name = xxx 22 | email = xxx 23 | [merge] 24 | tool = vimdiff 25 | [push] 26 | default = matching 27 | -------------------------------------------------------------------------------- /env/vimrc: -------------------------------------------------------------------------------- 1 | set nu 2 | sy on 3 | set mouse= 4 | set ruler 5 | set smartindent shiftwidth=4 6 | set tabstop=4 7 | set expandtab 8 | 9 | set listchars=tab:>-,trail:~ 10 | set list 11 | colorscheme desert 12 | 13 | com E e. 14 | -------------------------------------------------------------------------------- /k8s/cpp-note-pod.yml: -------------------------------------------------------------------------------- 1 | # chrono @ 2021-03 2 | 3 | # kubernetes pod yaml for cpp note 4 | # you could run it in k8s/minikube/kind/... 5 | 6 | # kubectl apply -f cpp-note-pod.yml 7 | # kubectl delete -f cpp-note-pod.yml 8 | # 9 | # kubectl get pods 10 | # kubectl exec -it k8s-cpp-note -- bash 11 | # kubectl attach -it k8s-cpp-note 12 | 13 | apiVersion: v1 14 | kind: Pod 15 | 16 | metadata: 17 | name: k8s-cpp-note 18 | labels: 19 | author: chrono 20 | lang: cpp 21 | env: study 22 | 23 | spec: 24 | 25 | containers: 26 | 27 | - name: cpp-note 28 | image: chronolaw/cpp_note:gcc7 29 | #image: chronolaw/cpp_note:gcc10 30 | workingDir: /root/cpp_note 31 | 32 | # exec or attach into this container 33 | stdin: true 34 | tty: true 35 | 36 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #GCC=gcc:10 4 | #GCC=gcc:7 5 | 6 | #GCC=chronolaw/cpp_note:gcc10 7 | #GCC=chronolaw/cpp_note:gcc7 8 | 9 | GCC=gcc7 10 | 11 | if [ $# -ne 0 ]; then 12 | #echo $1 13 | GCC=$1 14 | fi 15 | 16 | #echo ${GCC} 17 | #exit 18 | 19 | IMAGE="chronolaw/cpp_note:${GCC}" 20 | 21 | #docker run -it --rm -v ${PWD}:/tmp:ro ${GCC} 22 | #docker run -it --rm -v ${PWD}:/tmp ${GCC} 23 | 24 | #docker run -it --rm ${IMAGE} 25 | docker run -it --rm -v ${PWD}:/tmp ${IMAGE} 26 | 27 | --------------------------------------------------------------------------------