diff --git a/README.md b/README.md index 2c0323e..3b1a993 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ### 0.项目概要 -学习C++内容,包括理论、源码、实践、课程代码、项目等 +学习C++内容,包括理论、源码、实践、课程代码、项目等。 ### 1.基础部分 @@ -146,6 +146,7 @@ for(decl:col) { - [是不是应该返回对象?](./modern_C++_30/returnObj) - [编译期多态:泛型编程和模板入门](./modern_C++_30/compilerpoly) - [SFINAE:不是错误的替换失败是怎么回事?](./modern_C++_30/SFINAE) +- [constexpr:一个常态的世界](./modern_C++_30/constexpr) ### 4.拓展部分 diff --git a/modern_C++_30/.CMakeLists.txt.un~ b/modern_C++_30/.CMakeLists.txt.un~ index 65349bb..49bafb8 100644 Binary files a/modern_C++_30/.CMakeLists.txt.un~ and b/modern_C++_30/.CMakeLists.txt.un~ differ diff --git a/modern_C++_30/CMakeLists.txt b/modern_C++_30/CMakeLists.txt index 96a917d..b29314f 100644 --- a/modern_C++_30/CMakeLists.txt +++ b/modern_C++_30/CMakeLists.txt @@ -62,3 +62,7 @@ add_executable(lambda "SFINAE/sfinae paper/lambda.cpp") add_executable(is_valid "SFINAE/sfinae paper/is_valid.cpp") add_executable(fis_valid "SFINAE/sfinae paper/fis_valid.cpp") add_executable(packis_valid "SFINAE/sfinae paper/packis_valid.cpp") + + +add_executable(test3 constexpr/test3.cpp) +add_executable(sqrt constexpr/sqrt.cpp) diff --git a/modern_C++_30/CMakeLists.txt~ b/modern_C++_30/CMakeLists.txt~ new file mode 100644 index 0000000..96a917d --- /dev/null +++ b/modern_C++_30/CMakeLists.txt~ @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 3.14) +project(Morden_C++) + +set(CMAKE_CXX_STANDARD 17) + +add_executable(heap RAII/heap.cpp) +add_executable(stack RAII/stack.cpp) +add_executable(RAII RAII/RAII.cpp) +add_executable(RAII_fstram RAII/RAII_fstram.cpp) + +add_executable(auto_scope smart_ptr/auto_scope.cpp) +add_executable(unique_ptr smart_ptr/unique_ptr.cpp) +add_executable(unique_ptr_U smart_ptr/unique_ptr_U.cpp) +add_executable(shared_ptr smart_ptr/shared_ptr.cpp) + +add_executable(reference reference/reference.cpp) +add_executable(forward reference/forward.cpp) +add_executable(collapses reference/collapses.cpp) +add_executable(lifetime reference/lifetime.cpp) +add_executable(dontreturnReference reference/don'treturnReference.cpp) + +add_executable(container container1/container.cpp) +add_executable(cont container2/hash.cpp) +add_executable(vector_l container1/vector_l.cpp) +add_executable(priority_queue container2/priority_queue.cpp) +add_executable(relacontainer container2/relacontainer.cpp) +add_executable(unorder container2/unorder.cpp) +add_executable(array container2/array.cpp) +add_executable(exception exception/exception.cpp) + + +add_executable(returnObj returnObj/returnObj1.cpp) +add_executable(returnObj_add returnObj/returnObj2.cpp) +add_executable(returnObj3 returnObj/returnObj3.cpp) +add_executable(returnObj4 returnObj/returnObj4.cpp) +add_executable(returnObj5 returnObj/returnObj5.cpp) +add_executable(rvonrvo returnObj/all.cpp) + +add_executable(literal literalAssert/literal.cpp) +add_executable(assert literalAssert/assert.cpp) +add_executable(default_delete literalAssert/default_delete.cpp) +add_executable(overridefinal literalAssert/overridefinal.cpp) + + +add_executable(SFINAE "SFINAE/SFINAE.cpp") +add_executable(serialize "SFINAE/sfinae paper/serialize.cpp") +add_executable(hana "SFINAE/sfinae paper/hana.cpp") +add_executable(overload "SFINAE/sfinae paper/overload1.cpp") +add_executable(pSFINAE "SFINAE/sfinae paper/p1SFINAE.cpp") +add_executable(p1SFINAE "SFINAE/sfinae paper/p2SFINAE.cpp") +add_executable(sizeof1 "SFINAE/sfinae paper/sizeof1.cpp") +add_executable(sizeof2 "SFINAE/sfinae paper/sizeof2.cpp") +add_executable(combining "SFINAE/sfinae paper/combiningAndGenius.cpp") +add_executable(overload2 "SFINAE/sfinae paper/overload2.cpp") +add_executable(combining1 "SFINAE/sfinae paper/timeGenius.cpp") +add_executable(decltype "SFINAE/sfinae paper/decltype.cpp") +add_executable(auto "SFINAE/sfinae paper/auto.cpp") +add_executable(constexpr "SFINAE/sfinae paper/constexpr.cpp") +add_executable(blending "SFINAE/sfinae paper/blending1.cpp") +add_executable(blending2 "SFINAE/sfinae paper/blending2.cpp") +add_executable(lambda "SFINAE/sfinae paper/lambda.cpp") +add_executable(is_valid "SFINAE/sfinae paper/is_valid.cpp") +add_executable(fis_valid "SFINAE/sfinae paper/fis_valid.cpp") +add_executable(packis_valid "SFINAE/sfinae paper/packis_valid.cpp") diff --git a/modern_C++_30/constexpr/a.out b/modern_C++_30/constexpr/a.out new file mode 100755 index 0000000..011df3e Binary files /dev/null and b/modern_C++_30/constexpr/a.out differ diff --git a/modern_C++_30/constexpr/container.cpp b/modern_C++_30/constexpr/container.cpp new file mode 100644 index 0000000..bf2cd74 --- /dev/null +++ b/modern_C++_30/constexpr/container.cpp @@ -0,0 +1,43 @@ +// +// Created by light on 19-12-16. +// + +#include +#include +#include +#include +#include "output_container.h" + + +using namespace std; + +int main() { + map mp{ + {1, 1}, + {2, 4}, + {3, 9}}; + cout << mp << endl; + vector> vv{ + {1, 1}, + {2, 4}, + {3, 9}}; + cout << vv << endl; + + pair p{1, 2}; + cout << p << endl; + + set s{1, 2, 3}; + cout << s << endl; + + vector v{'a', 'b'}; + cout << v << endl; + set vs{"a", "b"}; + cout << vs << endl; + + map mm{ + {1, "23"}, + {2, "234hi"} + }; + cout << mm << endl; + +} diff --git a/modern_C++_30/constexpr/newconstexpr.cpp b/modern_C++_30/constexpr/newconstexpr.cpp new file mode 100644 index 0000000..b8b9570 --- /dev/null +++ b/modern_C++_30/constexpr/newconstexpr.cpp @@ -0,0 +1,78 @@ +// +// Created by light on 20-1-7. +// + +#include +#include +#include + +using namespace std; + +// C++17 内联变量 +struct magic { +// static const int number = 42; // error + static constexpr int number = 42; // ok +// 类的静态constexpr成员变量默认就是内联的。 +// static inline const int number = 42; // ok +// const常量和类外面的constexpr变量是不默认内联,需要手工加inline关键字才会变成内联 +}; + +// 内联变量之前用这个方法,称为one definition rule,有了内联变量及模板,则不受这条规则限制! +// const int magic::number = 42; // ok + + +// C++14 变量模板 +// 之前我们需要用类静态数据成员来表达的东西,使用变量模板可以更简洁地表达。 +namespace my { + template + inline constexpr bool + is_trivially_destructible_v = + std::is_trivially_destructible< + T>::value; +} +// 不重要析构 +class A { +}; + +// 重要析构 +class B { + ~B() {} +}; + +int main() { + std::cout << magic::number << std::endl; + + std::vector v; + v.push_back(magic::number); // undefined reference to `magic::number' + std::cout << v[0] << std::endl; + // 不重要的析构 + std::cout << is_trivially_destructible_v << std::endl; + std::cout << is_trivially_destructible_v << std::endl; + + // constexpr变量仍是const + + constexpr int a = 42; + const int &b = a; + // 上述const不能去掉,否则报如下错误: + // binding reference of type ‘int&’ to ‘const int’ discards qualifiers + + + // constexpr 构造函数和字面类型 + // C++14 放开了 constexpr函数里的循环 + // C++20 放开了 try...catch语句 和 asm声明 + // constexpr函数里不能使用goto语句 + + // 一个有意思的情况是一个类的构造函数。如果一个类的构造函数里面只包含常量表达式、 + // 满足对 constexpr 函数的限制的话(这也意味着,里面不可以有任何动态内存分配), + // 并且类的析构函数是平凡的,那这个类就可以被称为是一个字面类型。 + std::array ay; + + + constexpr string_view sv{"hi"}; + constexpr pair pr{sv[0], sv[1]}; + constexpr array aa{pr.first, pr.second}; + constexpr int n1 = aa[0]; + constexpr int n2 = aa[1]; + cout << n1 << ' ' << n2 << '\n'; + +} \ No newline at end of file diff --git a/modern_C++_30/constexpr/output_container.h b/modern_C++_30/constexpr/output_container.h new file mode 100644 index 0000000..f7f038f --- /dev/null +++ b/modern_C++_30/constexpr/output_container.h @@ -0,0 +1,150 @@ +// +// Created by light on 20-1-8. +// + +#ifndef MORDEN_C_OUTPUT_CONTAINER_H +#define MORDEN_C_OUTPUT_CONTAINER_H + +#include // std::ostream +#include // std::false_type/true_type/decay_t/is_same_v +#include // std::declval/pair + +// 检测是否是pair +template +struct is_pair : std::false_type { +}; +template +struct is_pair> : std::true_type { +}; +template +inline constexpr bool is_pair_v = is_pair::value; + +// 检测是否可以直接输出 +template +struct has_output_function { + template + static auto output(U *ptr) + -> decltype(std::declval() << *ptr, + std::true_type()); + + template + static std::false_type output(...); + + static constexpr bool value = + decltype(output(nullptr))::value; +}; + +template +inline constexpr bool has_output_function_v = + has_output_function::value; + + +enum CHARS { + ORD, // 其他类型 + CHAR, // char 类型 + STRING // string 类型 +}; + +template +int ischarOrString(T &elem) { + using std::decay_t; + using std::is_same_v; + using element_type = decay_t; + constexpr bool is_char_v = is_same_v; + constexpr bool is_string_v = is_same_v || + is_same_v || + is_same_v; + if (is_char_v) + return CHAR; + else if (is_string_v) + return STRING; + else + return ORD; +} + +template +void output(T &elem, int type, std::ostream &os) { + switch (type) { + case CHAR: + os << '\'' << elem << '\''; + break; + case STRING: + os << '\"' << elem << '\"'; + break; + case ORD: + os << elem; + break; + } +} + +template +auto output_element(std::ostream &os, const T &element, + const Cont &) +-> typename std::enable_if::value, bool>::type { + int ftype = ischarOrString(element.first); + int stype = ischarOrString(element.second); + + output(element.first, ftype, os); + os << " => "; + output(element.second, stype, os); + return true; +} + +template +auto output_element(std::ostream &os, const T &element, + const Cont &) +-> typename std::enable_if::value, bool>::type { + int etype = ischarOrString(element); + output(element, etype, os); + return false; +} + +template +std::ostream &operator<<(std::ostream &os, const std::pair &pr) { + os << '(' << pr.first << ", " << pr.second << ')'; + return os; +} + +//template +//auto output_element(std::ostream& os, const T& element, +// const Cont&, const std::true_type) +//-> decltype(std::declval(), os) +//{ +// os << element.first << " => " << element.second; +// return os; +//} +// +//template +//auto output_element(std::ostream& os, const T& element, +// const Cont&, ...) +//-> decltype(os) +//{ +// os << element; +// return os; +//} + + + +// 针对没有输出函数的容器处理 +template>> +auto operator<<(std::ostream &os, const T &container) +-> decltype(container.begin(), container.end(), os) { + os << "{ "; + if (!container.empty()) { + bool on_first_element = true; + for (auto elem:container) { + if (!on_first_element) { + os << ", "; + } else { + on_first_element = false; + } + output_element(os, elem, container); + } + } + os << " }"; + return os; +} + + +#endif //MORDEN_C_OUTPUT_CONTAINER_H diff --git a/modern_C++_30/constexpr/sqrt.cpp b/modern_C++_30/constexpr/sqrt.cpp new file mode 100644 index 0000000..6a12987 --- /dev/null +++ b/modern_C++_30/constexpr/sqrt.cpp @@ -0,0 +1,47 @@ +// +// Created by light on 20-1-7. +// + +#include +#include + +int sqr(int n) { + return n * n; +} + +int rand() { + return std::rand(); +} + +// constant expression +constexpr int sqr1(int n) { + return n * n; +} + +constexpr int factorial(int n) { + // n是普通的int 不能使用static_assert +// static_assert(n>=0); //error + // 正确方式 + if (n < 0) { + throw std::invalid_argument( + "Arg must be non-negative"); + } + + if (n == 0) { + return 1; + } else { + return n * factorial(n - 1); + } +} + +int main() { + int a[sqr(3)]; // ok + const int n1 = sqr(3); // ok + + constexpr int n = sqr1(3); // constexpr=constant expression 常量表达式 + std::array aa; // ok + + std::array b; // ok + int cc[rand()]; + return 0; +} \ No newline at end of file diff --git a/modern_C++_30/constexpr/test3.cpp b/modern_C++_30/constexpr/test3.cpp new file mode 100644 index 0000000..73e8924 --- /dev/null +++ b/modern_C++_30/constexpr/test3.cpp @@ -0,0 +1,31 @@ +// +// Created by light on 20-1-10. +// + +#include + +class test3 { +public: + + int value; + + // constexpr const method - can't chanage the values of object fields and can be evaluated at compile time. + constexpr int getvalue() const { + return (value); + } + + constexpr test3(int Value) + : value(Value) { + } +}; + + +int main() { + + // 加不加都行 + constexpr test3 x(100); // OK. Constructor is constexpr. + + int array[x.getvalue()]; // OK. x.getvalue() is constexpr and can be evaluated at compile time. +} + +