From 838d30ef5ab187dba38af6618f6d9be322c681a4 Mon Sep 17 00:00:00 2001 From: Changkun Ou Date: Mon, 2 Apr 2018 00:28:05 +0200 Subject: [PATCH] =?UTF-8?q?revision=20#1:=20=E6=9B=B4=E6=96=B0=E7=AC=AC?= =?UTF-8?q?=E4=BA=8C=E7=AB=A0=E4=B8=AD=E5=B7=B2=E7=BB=B4=E6=8A=A4=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + code/1/{1.1.cpp => 1.1.c.and.cpp} | 4 +- code/1/Makefile | 10 ++-- code/1/foo.c | 4 +- code/1/foo.h | 2 +- code/2/2.1.cpp | 32 ---------- code/2/2.1.nullptr.cpp | 34 +++++++++++ code/2/2.10.if.constexpr.cpp | 31 ++++++++++ code/2/2.11.for.loop.cpp | 23 ++++++++ code/2/2.2.constexpr.cpp | 50 ++++++++++++++++ code/2/2.2.cpp | 34 ----------- code/2/2.3.if.switch.cpp | 31 ++++++++++ code/2/2.4.initializer.list.cpp | 59 +++++++++++++++++++ code/2/2.5.cpp | 34 ----------- code/2/2.5.structured.binding.cpp | 20 +++++++ code/2/2.6.auto.cpp | 42 +++++++++++++ code/2/2.7.decltype.cpp | 23 ++++++++ code/2/2.8.tail.return.type.cpp | 46 +++++++++++++++ code/2/2.9.decltype.auto.cpp | 21 +++++++ code/2/Makefile | 7 +++ code/2/{2.3.cpp => todo/2.6.autox.cpp} | 2 +- code/2/{ => todo}/2.7.cpp | 0 code/2/{ => todo}/2.8.cpp | 0 code/2/todo/2.xxx.cpp | 21 +++++++ code/2/todo/fold.expression.cpp | 8 +++ exercises/2/fold.expresion.cpp | 8 +++ exercises/2/structured.binding.cpp | 22 +++++++ .../2/variadic.template.parameter.pack.cpp | 0 28 files changed, 460 insertions(+), 111 deletions(-) rename code/1/{1.1.cpp => 1.1.c.and.cpp} (84%) delete mode 100644 code/2/2.1.cpp create mode 100644 code/2/2.1.nullptr.cpp create mode 100644 code/2/2.10.if.constexpr.cpp create mode 100644 code/2/2.11.for.loop.cpp create mode 100644 code/2/2.2.constexpr.cpp delete mode 100644 code/2/2.2.cpp create mode 100644 code/2/2.3.if.switch.cpp create mode 100644 code/2/2.4.initializer.list.cpp delete mode 100644 code/2/2.5.cpp create mode 100644 code/2/2.5.structured.binding.cpp create mode 100644 code/2/2.6.auto.cpp create mode 100644 code/2/2.7.decltype.cpp create mode 100644 code/2/2.8.tail.return.type.cpp create mode 100644 code/2/2.9.decltype.auto.cpp create mode 100644 code/2/Makefile rename code/2/{2.3.cpp => todo/2.6.autox.cpp} (91%) rename code/2/{ => todo}/2.7.cpp (100%) rename code/2/{ => todo}/2.8.cpp (100%) create mode 100644 code/2/todo/2.xxx.cpp create mode 100644 code/2/todo/fold.expression.cpp create mode 100644 exercises/2/fold.expresion.cpp create mode 100644 exercises/2/structured.binding.cpp create mode 100644 exercises/2/variadic.template.parameter.pack.cpp diff --git a/.gitignore b/.gitignore index 4581ef2..8f7929a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ *.exe *.out *.app + +node_modules +website/public \ No newline at end of file diff --git a/code/1/1.1.cpp b/code/1/1.1.c.and.cpp similarity index 84% rename from code/1/1.1.cpp rename to code/1/1.1.c.and.cpp index 9a6690f..837626e 100644 --- a/code/1/1.1.cpp +++ b/code/1/1.1.c.and.cpp @@ -2,7 +2,7 @@ // 1.1.cpp // // chapter 1 introduction -// c++1x tutorial +// modern cpp tutorial // // created by changkun at changkun.de // @@ -12,7 +12,7 @@ #include int main() { - // 使用 lambda 表达式 + // use lambda expression [out = std::ref(std::cout << "Result from C code: " << add(1, 2))](){ out.get() << ".\n"; }(); diff --git a/code/1/Makefile b/code/1/Makefile index 267c715..e0d5b00 100644 --- a/code/1/Makefile +++ b/code/1/Makefile @@ -2,21 +2,21 @@ # 1.1.cpp # # chapter 1 introduction -# c++1x tutorial +# modern cpp tutorial # # created by changkun at changkun.de # C = gcc -CXX = g++ +CXX = clang++ SOURCE_C = foo.c OBJECTS_C = foo.o -SOURCE_CXX = 1.1.cpp +SOURCE_CXX = 1.1.c.and.cpp -TARGET = 1.1 -LDFLAGS_COMMON = -std=c++1z +TARGET = 1.1.out +LDFLAGS_COMMON = -std=c++17 all: $(C) -c $(SOURCE_C) diff --git a/code/1/foo.c b/code/1/foo.c index f16fca9..273bdd1 100644 --- a/code/1/foo.c +++ b/code/1/foo.c @@ -2,14 +2,14 @@ // foo.c // // chapter 1 introduction -// c++1x tutorial +// modern cpp tutorial // // created by changkun at changkun.de // #include "foo.h" -// C 语言代码 +// C code int add(int x, int y) { return x+y; } diff --git a/code/1/foo.h b/code/1/foo.h index 084fade..f10bf6e 100644 --- a/code/1/foo.h +++ b/code/1/foo.h @@ -2,7 +2,7 @@ // foo.h // // chapter 1 introduction -// c++1x tutorial +// modern cpp tutorial // // created by changkun at changkun.de // diff --git a/code/2/2.1.cpp b/code/2/2.1.cpp deleted file mode 100644 index f79e94b..0000000 --- a/code/2/2.1.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// -// 2.1.cpp -// c++1x tutorial -// -// created by changkun at changkun.de -// -// nullptr - -#include - -void foo(char *); -void foo(int); - -int main() { - - if(NULL == (void *)0) - std::cout << "NULL == 0" << std::endl; // 该行将输出 - else - std::cout << "NULL != 0" << std::endl; - - foo(0); // 调用 foo(int) - //foo(NULL); // 该行不能通过编译 - foo(nullptr); // 调用 foo(char*) - - return 0; -} -void foo(char *ch) { - std::cout << "call foo(char*)" << std::endl; -} -void foo(int i) { - std::cout << "call foo(int)" << std::endl; -} diff --git a/code/2/2.1.nullptr.cpp b/code/2/2.1.nullptr.cpp new file mode 100644 index 0000000..c0959f5 --- /dev/null +++ b/code/2/2.1.nullptr.cpp @@ -0,0 +1,34 @@ +// +// 2.1.nullptr.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include +#include + +void foo(char *); +void foo(int); + +int main() { + if (std::is_same::value) + std::cout << "NULL == 0" << std::endl; + if (std::is_same::value) + std::cout << "NULL == (void *)0" << std::endl; + if (std::is_same::value) + std::cout << "NULL == nullptr" << std::endl; + + foo(0); // will call foo(int) + // foo(NULL); // doen't compile + foo(nullptr); // will call foo(char*) + return 0; +} + +void foo(char *) { + std::cout << "foo(char*) is called" << std::endl; +} +void foo(int i) { + std::cout << "foo(int) is called" << std::endl; +} diff --git a/code/2/2.10.if.constexpr.cpp b/code/2/2.10.if.constexpr.cpp new file mode 100644 index 0000000..97f6dc7 --- /dev/null +++ b/code/2/2.10.if.constexpr.cpp @@ -0,0 +1,31 @@ +// +// 2.10.if.constexpr.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include + +template +auto print_type_info(const T& t) { + if constexpr (std::is_integral::value) { + return t + 1; + } else { + return t + 0.001; + } +} + +// at compiling time +// int print_type_info(const int& t) { +// return t + 1; +// } +// double print_type_info(const double& t) { +// return t + 0.001; +// } + +int main() { + std::cout << print_type_info(5) << std::endl; + std::cout << print_type_info(3.14) << std::endl; +} \ No newline at end of file diff --git a/code/2/2.11.for.loop.cpp b/code/2/2.11.for.loop.cpp new file mode 100644 index 0000000..fd0d7bf --- /dev/null +++ b/code/2/2.11.for.loop.cpp @@ -0,0 +1,23 @@ +// +// 2.11.for.loop.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include +#include +#include + +int main() { + std::vector vec = {1, 2, 3, 4}; + if (auto itr = std::find(vec.begin(), vec.end(), 3); itr != vec.end()) *itr = 4; + for (auto element : vec) + std::cout << element << std::endl; // read only + for (auto &element : vec) { + element += 1; // writeable + } + for (auto element : vec) + std::cout << element << std::endl; // read only +} \ No newline at end of file diff --git a/code/2/2.2.constexpr.cpp b/code/2/2.2.constexpr.cpp new file mode 100644 index 0000000..820e4e6 --- /dev/null +++ b/code/2/2.2.constexpr.cpp @@ -0,0 +1,50 @@ +// +// 2.2.constexpr.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include +#define LEN 10 + +int len_foo() { + int i = 2; + return i; +} +constexpr int len_foo_constexpr() { + return 5; +} + +// error in c++11 +// constexpr int fibonacci(const int n) { +// if(n == 1) return 1; +// if(n == 2) return 1; +// return fibonacci(n-1) + fibonacci(n-2); +// } + +// ok +constexpr int fibonacci(const int n) { + return n == 1 || n == 2 ? 1 : fibonacci(n-1) + fibonacci(n-2); +} + + +int main() { + char arr_1[10]; // legal + char arr_2[LEN]; // legal + + int len = 10; + // char arr_3[len]; // illegal + + const int len_2 = len + 1; + char arr_4[len_2]; // legal + + // char arr_5[len_foo()+5]; // illegal + char arr_6[len_foo_constexpr() + 1]; // legal + + // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 + std::cout << fibonacci(10) << std::endl; + + return 0; +} diff --git a/code/2/2.2.cpp b/code/2/2.2.cpp deleted file mode 100644 index ee94910..0000000 --- a/code/2/2.2.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// 2.2.cpp -// c++1x tutorial -// -// created by changkun at changkun.de -// -// constexpr - -#include -#define LEN 10 - -constexpr int len_foo() { - return 5; -} - -constexpr int fibonacci(const int n) { - return n == 1 || n == 2 ? 1 : fibonacci(n-1)+fibonacci(n-2); -} - -int main() { - char arr_1[10]; - - char arr_2[LEN]; - - const int len = 10; - char arr_3[len]; - - char arr_5[len_foo()+5]; - - std::cout << fibonacci(10) << std::endl; - // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 - - return 0; -} diff --git a/code/2/2.3.if.switch.cpp b/code/2/2.3.if.switch.cpp new file mode 100644 index 0000000..5651781 --- /dev/null +++ b/code/2/2.3.if.switch.cpp @@ -0,0 +1,31 @@ +// +// 2.3.if.switch.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include +#include +#include + +int main() { + std::vector vec = {1, 2, 3, 4}; + + // before c++17, can be simplefied by using `auto` + const std::vector::iterator itr = std::find(vec.begin(), vec.end(), 2); + if (itr != vec.end()) { + *itr = 3; + } + + // after c++17, can be simplefied by using `auto` + if (const std::vector::iterator itr = std::find(vec.begin(), vec.end(), 3); + itr != vec.end()) { + *itr = 4; + } + + // should output: 1, 4, 3, 4. can be simplefied using `auto` + for (std::vector::iterator element = vec.begin(); element != vec.end(); ++element) + std::cout << *element << std::endl; +} \ No newline at end of file diff --git a/code/2/2.4.initializer.list.cpp b/code/2/2.4.initializer.list.cpp new file mode 100644 index 0000000..9f2dbe0 --- /dev/null +++ b/code/2/2.4.initializer.list.cpp @@ -0,0 +1,59 @@ +// +// 2.4.initializer.list.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include +#include +#include + +class Foo { +public: + int value_a; + int value_b; + Foo(int a, int b) : value_a(a), value_b(b) {} +}; + +class MagicFoo { +public: + std::vector vec; + MagicFoo(std::initializer_list list) { + for (std::initializer_list::iterator it = list.begin(); it != list.end(); ++it) { + vec.push_back(*it); + } + } + void foo(std::initializer_list list) { + for (std::initializer_list::iterator it = list.begin(); it != list.end(); ++it) { + vec.push_back(*it); + } + } +}; + +int main() { + // before C++11 + int arr[3] = {1, 2, 3}; + Foo foo(1, 2); + std::vector vec = {1, 2, 3, 4, 5}; + + // after C++11 + MagicFoo magicFoo = {1, 2, 3, 4, 5}; + magicFoo.foo({6,7,8,9}); + Foo foo2 {3, 4}; + + std::cout << "arr[0]: " << arr[0] << std::endl; + std::cout << "foo:" << foo.value_a << ", " << foo.value_b << std::endl; + std::cout << "vec: "; + for (std::vector::iterator it = vec.begin(); it != vec.end(); ++it) { + std::cout << *it << std::endl; + } + std::cout << "magicFoo: "; + for (std::vector::iterator it = magicFoo.vec.begin(); it != magicFoo.vec.end(); ++it) { + std::cout << *it << std::endl; + } + std::cout << "foo2: " << foo2.value_a << ", " << foo2.value_b << std::endl; + + return 0; +} \ No newline at end of file diff --git a/code/2/2.5.cpp b/code/2/2.5.cpp deleted file mode 100644 index e082dd4..0000000 --- a/code/2/2.5.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// 2.5.cpp -// c++1x tutorial -// -// created by changkun at changkun.de -// -// 初始化列表 - - -#include - -class Foo { -private: - int value; -public: - Foo(int) {} -}; - -class Magic { -public: - Magic(std::initializer_list list) {} -}; - -void func(std::initializer_list list) { - return; -} - -int main() { - int arr[3] = {1,2,3}; // 列表初始化 - Foo foo(1); // 普通构造初始化 - - Magic magic = {1,2,3,4,5}; // 使用 initialize_list - func({1,2,3}); -} diff --git a/code/2/2.5.structured.binding.cpp b/code/2/2.5.structured.binding.cpp new file mode 100644 index 0000000..084763c --- /dev/null +++ b/code/2/2.5.structured.binding.cpp @@ -0,0 +1,20 @@ +// +// 2.5.structured.binding.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include +#include + +std::tuple f() { + return std::make_tuple(1, 2.3, "456"); +} + +int main() { + auto [x, y, z] = f(); + std::cout << x << ", " << y << ", " << z << std::endl; + return 0; +} diff --git a/code/2/2.6.auto.cpp b/code/2/2.6.auto.cpp new file mode 100644 index 0000000..bf01d67 --- /dev/null +++ b/code/2/2.6.auto.cpp @@ -0,0 +1,42 @@ +// +// 2.6.auto.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include +#include +#include + +class MagicFoo { +public: + std::vector vec; + MagicFoo(std::initializer_list list) { + for (auto it = list.begin(); it != list.end(); ++it) { + vec.push_back(*it); + } + } +}; + +// wrong +// int add(auto x, auto y) { +// return x+y; +// } + +int main() { + MagicFoo magicFoo = {1, 2, 3, 4, 5}; + std::cout << "magicFoo: "; + for (auto it = magicFoo.vec.begin(); it != magicFoo.vec.end(); ++it) { + std::cout << *it << ", "; + } + std::cout << std::endl; + + auto i = 5; // type int + auto j = 6; // type int + auto arr = new auto(10); // type int* + // auto auto_arr2[10] = arr; + // std::cout << add(i, j) << std::endl; + return 0; +} \ No newline at end of file diff --git a/code/2/2.7.decltype.cpp b/code/2/2.7.decltype.cpp new file mode 100644 index 0000000..6bac87a --- /dev/null +++ b/code/2/2.7.decltype.cpp @@ -0,0 +1,23 @@ +// +// 2.7.decltype.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include +#include + +int main() { + auto x = 1; + auto y = 2; + decltype(x+y) z = 3; + if (std::is_same::value) + std::cout << "type x == int" << std::endl; + if (std::is_same::value) + std::cout << "type z == float" << std::endl; + if (std::is_same::value) + std::cout << "type z == type x" << std::endl; + return 0; +} \ No newline at end of file diff --git a/code/2/2.8.tail.return.type.cpp b/code/2/2.8.tail.return.type.cpp new file mode 100644 index 0000000..414d4cd --- /dev/null +++ b/code/2/2.8.tail.return.type.cpp @@ -0,0 +1,46 @@ +// +// 2.8.tail.return.type.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +#include +#include + +// before c++11 +template +R add(T x, U y) { + return x + y; +} +// after c++11 +template +auto add2(T x, U y) -> decltype(x+y){ + return x + y; +} +// after c++14 +template +auto add3(T x, U y){ + return x + y; +} + +int main() { + + // before c++11 + int z = add(1, 2); + std::cout << z << std::endl; + + // after c++11 + auto w = add2(1, 2.0); + if (std::is_same::value) { + std::cout << "w is double: "; + } + std::cout << w << std::endl; + + // after c++14 + auto q = add3(1.0, 2); + std::cout << "q: " << q << std::endl; + + return 0; +} \ No newline at end of file diff --git a/code/2/2.9.decltype.auto.cpp b/code/2/2.9.decltype.auto.cpp new file mode 100644 index 0000000..5445fca --- /dev/null +++ b/code/2/2.9.decltype.auto.cpp @@ -0,0 +1,21 @@ +// +// 2.9.decltype.auto.cpp +// chapter 2 language usability +// modern cpp tutorial +// +// created by changkun at changkun.de +// + +template +struct Int {}; + +constexpr auto iter(Int<0>) -> Int<0>; + +template +constexpr auto iter(Int) { + return iter(Int{}); +} + +int main() { + decltype(iter(Int<10>{})) a; +} \ No newline at end of file diff --git a/code/2/Makefile b/code/2/Makefile new file mode 100644 index 0000000..60de27c --- /dev/null +++ b/code/2/Makefile @@ -0,0 +1,7 @@ +all: $(patsubst %.cpp, %.out, $(wildcard *.cpp)) + +%.out: %.cpp Makefile + clang++ $< -o $@ -std=c++17 + +clean: + rm *.out \ No newline at end of file diff --git a/code/2/2.3.cpp b/code/2/todo/2.6.autox.cpp similarity index 91% rename from code/2/2.3.cpp rename to code/2/todo/2.6.autox.cpp index e3d0387..e87c8fe 100644 --- a/code/2/2.3.cpp +++ b/code/2/todo/2.6.autox.cpp @@ -32,7 +32,7 @@ int main() { int arr[10] = {0}; auto auto_arr = arr; // 正确,对整个类型进行推导 - //auto auto_arr2[10] = arr; // 错误, 无法推导数组元素类型 + // auto auto_arr2[10] = arr; // 错误, 无法推导数组元素类型 auto x = 1; auto y = 2; diff --git a/code/2/2.7.cpp b/code/2/todo/2.7.cpp similarity index 100% rename from code/2/2.7.cpp rename to code/2/todo/2.7.cpp diff --git a/code/2/2.8.cpp b/code/2/todo/2.8.cpp similarity index 100% rename from code/2/2.8.cpp rename to code/2/todo/2.8.cpp diff --git a/code/2/todo/2.xxx.cpp b/code/2/todo/2.xxx.cpp new file mode 100644 index 0000000..c954dd1 --- /dev/null +++ b/code/2/todo/2.xxx.cpp @@ -0,0 +1,21 @@ +#include + +template +void printf(T0 value) { + std::cout << value << std::endl; +} +template +void printf(T value, Args... args) { + std::cout << value << std::endl; + printf(args...); +} + +template +void printf_short(T0 t0, T... t) { + std::cout << t0 << std::endl; + if constexpr (sizeof...(t) > 0) printf(t...); +} +int main() { + printf_short(1, 2, "123", 1.1); + return 0; +} \ No newline at end of file diff --git a/code/2/todo/fold.expression.cpp b/code/2/todo/fold.expression.cpp new file mode 100644 index 0000000..2911f75 --- /dev/null +++ b/code/2/todo/fold.expression.cpp @@ -0,0 +1,8 @@ +#include +template +auto sum(T ... t) { + return (t + ...); +} +int main() { + std::cout << sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << std::endl; +} \ No newline at end of file diff --git a/exercises/2/fold.expresion.cpp b/exercises/2/fold.expresion.cpp new file mode 100644 index 0000000..e241a1e --- /dev/null +++ b/exercises/2/fold.expresion.cpp @@ -0,0 +1,8 @@ +#include +template +auto average(T ... t) { + return (t + ... ) / sizeof...(t); +} +int main() { + std::cout << average(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << std::endl; +} \ No newline at end of file diff --git a/exercises/2/structured.binding.cpp b/exercises/2/structured.binding.cpp new file mode 100644 index 0000000..5881e89 --- /dev/null +++ b/exercises/2/structured.binding.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +template +void update(std::map& m, F foo) { + for (auto&& [key, value] : m ) value = foo(key); +} + +int main() { + std::map m { + {"a", 1}, + {"b", 2}, + {"c", 3} + }; + update(m, [](std::string key) -> long long int { + return std::hash{}(key); + }); + for (auto&& [key, value] : m) + std::cout << key << ":" << value << std::endl; +} \ No newline at end of file diff --git a/exercises/2/variadic.template.parameter.pack.cpp b/exercises/2/variadic.template.parameter.pack.cpp new file mode 100644 index 0000000..e69de29