support bazel complie this project and format code.

This commit is contained in:
zhangxing
2023-03-30 00:15:11 +08:00
committed by light-city
parent 1f86192576
commit 7529ae3a55
636 changed files with 10025 additions and 9387 deletions

View File

@@ -1,68 +0,0 @@
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")
add_executable(test3 constexpr/test3.cpp)
add_executable(sqrt constexpr/sqrt.cpp)

View File

@@ -1,64 +0,0 @@
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")

View File

@@ -1,96 +0,0 @@
#include <iostream>
#include <mutex>
#include <fstream>
using namespace std;
enum class shape_type {
circle,
triangle,
rectangle,
};
class shape {
public:
shape() { cout << "shape" << endl; }
virtual void print() {
cout << "I am shape" << endl;
}
virtual ~shape() {}
};
class circle : public shape {
public:
circle() { cout << "circle" << endl; }
void print() {
cout << "I am circle" << endl;
}
};
class triangle : public shape {
public:
triangle() { cout << "triangle" << endl; }
void print() {
cout << "I am triangle" << endl;
}
};
class rectangle : public shape {
public:
rectangle() { cout << "rectangle" << endl; }
void print() {
cout << "I am rectangle" << endl;
}
};
// 利用多态 上转 如果返回值为shape,会存在对象切片问题。
shape *create_shape(shape_type type) {
switch (type) {
case shape_type::circle:
return new circle();
case shape_type::triangle:
return new triangle();
case shape_type::rectangle:
return new rectangle();
}
}
class shape_wrapper {
public:
explicit shape_wrapper(shape *ptr = nullptr) : ptr_(ptr) {}
~shape_wrapper() {
delete ptr_;
}
shape *get() const {
return ptr_;
}
private:
shape *ptr_;
};
void foo() {
shape_wrapper ptr(create_shape(shape_type::circle));
ptr.get()->print();
}
int main() {
// 第一种方式
shape *sp = create_shape(shape_type::circle);
sp->print();
delete sp;
// 第二种方式
foo();
return 0;
}

View File

@@ -1,38 +0,0 @@
#include <iostream>
using namespace std;
class bar {
};
// java 程序员风格
void foo() {
cout << "method 1" << endl;
bar *ptr = new bar();
delete ptr;
}
bar *make_bar() {
bar *ptr = nullptr;
try {
ptr = new bar();
} catch (...) {
delete ptr;
throw;
}
return ptr;
}
// 独立出函数 分配和释放不在一个函数里
void foo1() {
cout << "method 2" << endl;
bar *ptr = make_bar();
delete ptr;
}
int main() {
foo();
foo1();
return 0;
}

View File

@@ -1,26 +0,0 @@
//
// Created by light on 19-12-9.
//
#include <iostream>
class Obj {
public:
Obj() { puts("Obj()"); }
~Obj() { puts("~Obj()"); }
};
void foo(int n)
{
Obj obj;
if (n == 42)
throw "life, the universe and everything";
}
// 不管是否发生了异常obj 的析构函数都会得到执行。
int main()
{
try {
foo(41);
foo(42);
}
catch (const char* s) {
puts(s);
}
}

View File

@@ -1,41 +0,0 @@
//
// Created by light on 20-1-5.
//
#include <iostream>
using namespace std;
template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct {
char a[2];
} Two;
template<typename C>
static One test(int C::*);
// Will be chosen if T is anything except a class.
template<typename C>
static Two test(...);
public:
enum {
Yes = sizeof(IsClassT<T>::test<T>(0)) == 1
};
enum {
No = !Yes
};
};
struct A {
};
int main() {
// 0不能转换为int int::*因为int不是类所以它不能有成员指针。
cout << IsClassT<int>::Yes << endl;
cout << IsClassT<A>::Yes << endl;
return 0;
}

View File

@@ -1,54 +0,0 @@
//
// Created by light on 19-12-28.
//
#include <iostream>
using namespace std;
// 使用template实现IF条件判断
template<bool cond,
typename Then,
typename Else>
struct IF;
template<typename Then,
typename Else>
struct IF<true, Then, Else> {
typedef Then result;
};
template<typename Then,
typename Else>
struct IF<false, Then, Else> {
typedef Else result;
};
// 判断奇数与偶数
template<int N>
struct isEven {
static const auto RES = IF<N & 1 == 0, true_type, false_type>::result::value;
};
template<int nums1, int nums2>
struct Add_ {
static const int value = nums1 + nums2;
};
template<int nums1, int nums2>
struct Sub_ {
static const int value = nums1 - nums2;
};
// 加减
template<bool cond, int nums1, int nums2>
struct addSub {
static const auto RES = IF<cond, Add_<nums1, nums2>, Sub_<nums1, nums2>>::result::value;
};
int main() {
cout << isEven<10>::RES << endl;
cout << addSub<true, 10, 2>::RES << endl;
}

View File

@@ -1,77 +0,0 @@
//
// Created by light on 20-1-5.
//
#include <iostream>
using namespace std;
// 使用template实现while循环
template<bool condition,
typename Body>
struct WhileLoop;
template<typename Body>
struct WhileLoop<true, Body> {
typedef typename WhileLoop<
Body::cond_value,
typename Body::next_type>::type
type;
};
template<typename Body>
struct WhileLoop<false, Body> {
typedef
typename Body::res_type type;
};
template<typename Body>
struct While {
typedef typename WhileLoop<Body::cond_value, Body>::type type;
};
template<typename Body>
using While_t = WhileLoop<Body::cond_value, Body>;
namespace my {
template<class T, T v>
struct integral_constant {
static const T value = v;
typedef T value_type;
typedef integral_constant<T, v> type;
};
}
template<int result, int n>
struct SumLoop {
// 循环的条件
static const bool cond_value =
n != 0;
// 循环后的结果
static const int res_value =
result;
// 循环时的状态
typedef my::integral_constant<
int, res_value>
res_type;
// 循环执行一次时的状态
typedef SumLoop<result + n, n - 1>
next_type;
};
template<int n>
struct Sum {
typedef SumLoop<0, n> type;
};
template<int n>
using Sum_t = SumLoop<0, n>;
int main() {
cout << While<Sum<6>::type>::type::value << endl;
cout << While_t<Sum_t<6>>::type::value << endl;
return 0;
}

View File

@@ -1,24 +0,0 @@
//
// Created by light on 19-12-28.
//
#include <iostream>
using namespace std;
template<int n>
struct factorial {
static_assert(n >= 0, "Arg must be non-negative");
static const int value = n * factorial<n - 1>::value;
};
template<>
struct factorial<0> {
static const int value = 1;
};
int main() {
printf("%d\n", factorial<-1>::value);
return 0;
}

View File

@@ -1,39 +0,0 @@
//
// Created by light on 20-1-5.
//
#include <iostream>
#include <vector>
using namespace std;
template<
template<typename, typename>
class OutContainer = vector,
typename F, class R>
auto fmap(F &&f, R &&inputs) {
typedef decay_t<decltype(f(*inputs.begin()))> result_type;
OutContainer<result_type, allocator<result_type >> result;
for (auto &&item:inputs) {
result.push_back(f(item));
}
return result;
}
// 对每一个数进行加1操作
int add_1(int x) {
return x + 1;
}
int main() {
vector<int> v{1, 2, 3, 4, 5};
auto result = fmap(add_1, v);
for (auto item:result)
cout << item << " ";
cout<<endl;
return 0;
}

View File

@@ -1,43 +0,0 @@
//
// Created by light on 19-12-16.
//
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include "output_container.h"
using namespace std;
int main() {
map<int, int> mp{
{1, 1},
{2, 4},
{3, 9}};
cout << mp << endl;
vector<vector<int>> vv{
{1, 1},
{2, 4},
{3, 9}};
cout << vv << endl;
pair<int, int> p{1, 2};
cout << p << endl;
set<int> s{1, 2, 3};
cout << s << endl;
vector<char> v{'a', 'b'};
cout << v << endl;
set<char *> vs{"a", "b"};
cout << vs << endl;
map<int, char *> mm{
{1, "23"},
{2, "234hi"}
};
cout << mm << endl;
}

View File

@@ -1,78 +0,0 @@
//
// Created by light on 20-1-7.
//
#include <iostream>
#include <vector>
#include <array>
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<class T>
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<int> v;
v.push_back(magic::number); // undefined reference to `magic::number'
std::cout << v[0] << std::endl;
// 不重要的析构
std::cout << is_trivially_destructible_v<A> << std::endl;
std::cout << is_trivially_destructible_v<B> << 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<int, 5> 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';
}

View File

@@ -1,150 +0,0 @@
//
// Created by light on 20-1-8.
//
#ifndef MORDEN_C_OUTPUT_CONTAINER_H
#define MORDEN_C_OUTPUT_CONTAINER_H
#include <ostream> // std::ostream
#include <type_traits> // std::false_type/true_type/decay_t/is_same_v
#include <utility> // std::declval/pair
// 检测是否是pair
template<typename T>
struct is_pair : std::false_type {
};
template<typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type {
};
template<typename T>
inline constexpr bool is_pair_v = is_pair<T>::value;
// 检测是否可以直接输出
template<typename T>
struct has_output_function {
template<class U>
static auto output(U *ptr)
-> decltype(std::declval<std::ostream &>() << *ptr,
std::true_type());
template<class U>
static std::false_type output(...);
static constexpr bool value =
decltype(output<T>(nullptr))::value;
};
template<typename T>
inline constexpr bool has_output_function_v =
has_output_function<T>::value;
enum CHARS {
ORD, // 其他类型
CHAR, // char 类型
STRING // string 类型
};
template<typename T>
int ischarOrString(T &elem) {
using std::decay_t;
using std::is_same_v;
using element_type = decay_t<decltype(elem)>;
constexpr bool is_char_v = is_same_v<element_type, char>;
constexpr bool is_string_v = is_same_v<element_type, char *> ||
is_same_v<element_type, const char *> ||
is_same_v<element_type, std::string>;
if (is_char_v)
return CHAR;
else if (is_string_v)
return STRING;
else
return ORD;
}
template<typename T>
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<typename T, typename Cont>
auto output_element(std::ostream &os, const T &element,
const Cont &)
-> typename std::enable_if<is_pair<typename Cont::value_type>::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<typename T, typename Cont>
auto output_element(std::ostream &os, const T &element,
const Cont &)
-> typename std::enable_if<!is_pair<typename Cont::value_type>::value, bool>::type {
int etype = ischarOrString(element);
output(element, etype, os);
return false;
}
template<typename T, typename U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &pr) {
os << '(' << pr.first << ", " << pr.second << ')';
return os;
}
//template<typename T, typename Cont>
//auto output_element(std::ostream& os, const T& element,
// const Cont&, const std::true_type)
//-> decltype(std::declval<typename Cont::key_type>(), os)
//{
// os << element.first << " => " << element.second;
// return os;
//}
//
//template <typename T, typename Cont>
//auto output_element(std::ostream& os, const T& element,
// const Cont&, ...)
//-> decltype(os)
//{
// os << element;
// return os;
//}
// 针对没有输出函数的容器处理
template<typename T,
typename = std::enable_if_t<!has_output_function_v<T>>>
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

View File

@@ -1,47 +0,0 @@
//
// Created by light on 20-1-7.
//
#include <iostream>
#include <array>
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<int, n> aa; // ok
std::array<int, factorial(10)> b; // ok
int cc[rand()];
return 0;
}

View File

@@ -1,31 +0,0 @@
//
// Created by light on 20-1-10.
//
#include <iostream>
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.
}

View File

@@ -1,21 +0,0 @@
//
// Created by light on 19-12-16.
//
#include <iostream>
#include <map>
#include <vector>
#include "output_container.h"
using namespace std;
int main()
{
map<int, int> mp{
{1, 1}, {2, 4}, {3, 9}};
cout << mp << endl;
vector<vector<int>> vv{
{1, 1}, {2, 4}, {3, 9}};
cout << vv << endl;
}

View File

@@ -1,148 +0,0 @@
/*
* Written by Wu Yongwei <wuyongwei AT gmail DOT com>.
*
* Using this file requires a C++17-compliant compiler.
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* For more information, please refer to <http://unlicense.org>
*
*/
#ifndef OUTPUT_CONTAINER_H
#define OUTPUT_CONTAINER_H
#include <ostream> // std::ostream
#include <type_traits> // std::false_type/true_type/decay_t/is_same_v
#include <utility> // std::declval/pair
// Type trait to detect std::pair
template <typename T>
struct is_pair : std::false_type {};
template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type {};
template <typename T>
inline constexpr bool is_pair_v = is_pair<T>::value;
// Type trait to detect whether an output function already exists
template <typename T>
struct has_output_function {
template <class U>
static auto output(U* ptr)
-> decltype(std::declval<std::ostream&>() << *ptr,
std::true_type());
template <class U>
static std::false_type output(...);
static constexpr bool value =
decltype(output<T>(nullptr))::value;
};
template <typename T>
inline constexpr bool has_output_function_v =
has_output_function<T>::value;
/* NB: Visual Studio 2017 (or below) may have problems with
* has_output_function_v<T>: you should then use
* has_output_function<T>::value instead, or upgrade to
* Visual Studio 2019. */
// Output function for std::pair
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& pr);
// Element output function for containers that define a key_type and
// have its value type as std::pair
template <typename T, typename Cont>
auto output_element(std::ostream& os, const T& element,
const Cont&, const std::true_type)
-> decltype(std::declval<typename Cont::key_type>(), os);
// Element output function for other containers
template <typename T, typename Cont>
auto output_element(std::ostream& os, const T& element,
const Cont&, ...)
-> decltype(os);
// Main output function, enabled only if no output function already exists
template <typename T,
typename = std::enable_if_t<!has_output_function_v<T>>>
auto operator<<(std::ostream& os, const T& container)
-> decltype(container.begin(), container.end(), os)
{
using std::decay_t;
using std::is_same_v;
using element_type = decay_t<decltype(*container.begin())>;
constexpr bool is_char_v = is_same_v<element_type, char>;
if constexpr (!is_char_v) {
os << "{ ";
}
if (!container.empty()) {
auto end = container.end();
bool on_first_element = true;
for (auto it = container.begin(); it != end; ++it) {
if constexpr (is_char_v) {
if (*it == '\0') {
break;
}
}
if constexpr (!is_char_v) {
if (!on_first_element) {
os << ", ";
} else {
on_first_element = false;
}
}
output_element(os, *it, container, is_pair<element_type>());
}
}
if constexpr (!is_char_v) {
os << " }";
}
return os;
}
template <typename T, typename Cont>
auto output_element(std::ostream& os, const T& element,
const Cont&, const std::true_type)
-> decltype(std::declval<typename Cont::key_type>(), os)
{
os << element.first << " => " << element.second;
return os;
}
template <typename T, typename Cont>
auto output_element(std::ostream& os, const T& element,
const Cont&, ...)
-> decltype(os)
{
os << element;
return os;
}
template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& pr)
{
os << '(' << pr.first << ", " << pr.second << ')';
return os;
}
#endif // OUTPUT_CONTAINER_H

View File

@@ -1,64 +0,0 @@
//
// Created by light on 19-12-16.
//
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
class Obj1 {
public:
Obj1()
{
cout << "Obj1()\n";
}
Obj1(const Obj1&)
{
cout << "Obj1(const Obj1&)\n";
}
Obj1(Obj1&&)
{
cout << "Obj1(Obj1&&)\n";
}
};
class Obj2 {
public:
Obj2()
{
cout << "Obj2()\n";
}
Obj2(const Obj2&)
{
cout << "Obj2(const Obj2&)\n";
}
Obj2(Obj2&&) noexcept
{
cout << "Obj2(Obj2&&)\n";
}
};
int main()
{
vector<int> v;
int nums = 20;
for (int i = 0; i < nums; ++i) {
v.push_back(i + 1);
cout << "v_size: " << v.size() << "\t v_capacity: " << v.capacity() << endl;
}
// 头两个在已有空间上成功构造。第三个时发现空间不足,系统会请求更大的空间,大小由实现决定(比如两倍)。
// 有了足够的空间后就会在新空间的第三个的位置构造第三个obj1成功之后再把头两个拷贝或移动过来。
vector<Obj1> v1;
// v1.reserve(2);
v1.emplace_back();
v1.emplace_back();
v1.emplace_back();
v1.emplace_back();
vector<Obj2> v2;
v2.reserve(2);
v2.emplace_back();
v2.emplace_back();
v2.emplace_back();
}

View File

@@ -1,53 +0,0 @@
//
// Created by light on 19-12-16.
//
#include <iostream>
#include <map> // std::map
#include "../container1/output_container.h"
using namespace std;
#define ARRAY_LEN(a) \
(sizeof(a) / sizeof((a)[0]))
void test(int a[8]) {
cout << ARRAY_LEN(a) << endl;
}
void test1(int arr[]) {
// 不能编译
// std::cout << std::size(arr)
// << std::endl;
}
typedef char mykey_t[8];
typedef std::array<char, 8> mykey_t1;
int main() {
int a[8];
test(a);
// C++17 直接提供了一个 size 方法,可以用于提供数组长度,
int arr[] = {1, 2, 3, 4, 5};
std::cout << "The array length is "
<< std::size(arr)
<< std::endl;
// 并且在数组退化成指针的情况下会直接失败
test1(arr);
std::map<mykey_t, int> mp;
mykey_t mykey{"hello"};
// mp[mykey] = 5;
// 轰,大段的编译错误
std::map<mykey_t1, int> mp1;
mykey_t1 mykey1{"hello"};
mp1[mykey1] = 5; // ok
cout << mp1 << endl;
}

View File

@@ -1,46 +0,0 @@
//
// Created by light on 19-12-16.
//
#include <algorithm> // std::sort
#include <functional> // std::less/greater/hash
#include <iostream> // std::cout/endl
#include <string> // std::string
#include <vector> // std::vector
#include "../container1/output_container.h"
using namespace std;
int main()
{
// 初始数组
vector<int> v{13, 6, 4, 11, 29};
cout << v << endl;
// 从小到大排序
sort(v.begin(), v.end());
cout << v << endl;
// 从大到小排序
sort(v.begin(), v.end(),
greater<int>());
cout << v << endl;
cout << hex;
auto hp = hash<int*>();
cout << "hash(nullptr) = "
<< hp(nullptr) << endl;
cout << "hash(v.data()) = "
<< hp(v.data()) << endl;
cout << "v.data() = "
<< static_cast<void*>(v.data())
<< endl;
auto hs = hash<string>();
cout << "hash(\"hello\") = "
<< hs(string("hello")) << endl;
cout << "hash(\"hellp\") = "
<< hs(string("hellp")) << endl;
}

View File

@@ -1,30 +0,0 @@
//
// Created by light on 19-12-16.
//
#include <functional> // std::greater
#include <iostream> // std::cout/endl
#include <memory> // std::pair
#include <queue> // std::priority_queue
#include <vector> // std::vector
#include "../container1/output_container.h"
using namespace std;
int main()
{
priority_queue<
pair<int, int>,
vector<pair<int, int>>,
greater<pair<int, int>>>
q;
q.push({1, 1});
q.push({2, 2});
q.push({0, 3});
q.push({9, 4});
while (!q.empty()) {
cout << q.top() << endl;
q.pop();
}
}

View File

@@ -1,73 +0,0 @@
//
// Created by light on 19-12-16.
//
#include <iostream>
#include <functional>
#include <map>
#include <set>
#include <string>
#include "../container1/output_container.h"
#include <tuple>
using namespace std;
int main() {
set<int> s{1, 1, 1, 2, 3, 4};
cout << s << endl;
multiset<int, greater<int>> ms{1, 1, 1, 2, 3, 4};
cout << ms << endl;
map<string, int> mp{
{"one", 1},
{"two", 2},
{"three", 3},
{"four", 4}
};
cout << mp << endl;
mp.insert({"four", 4});
cout << mp << endl;
cout << (mp.find("four") == mp.end()) << endl;
cout << (mp.find("five") == mp.end()) << endl;
mp["five"] = 5;
cout << mp << endl;
multimap<string, int> mmp{
{"one", 1},
{"two", 2},
{"three", 3},
{"four", 4}
};
cout << mmp << endl;
mmp.insert({"four", -4});
cout << mmp << endl;
cout << (mp.find("four")->second) << endl;
cout << (mp.lower_bound("four")->second) << endl;
cout << (mp.upper_bound("four")->second) << endl;
cout << ((--mp.upper_bound("four"))->second) << endl;
multimap<string, int>::iterator
lower, upper;
std::tie(lower, upper) =
mmp.equal_range("four");
cout << (lower != upper) << endl; // 检测区间非空
cout << lower->second << endl;
cout << (--upper)->second << endl;
}

View File

@@ -1,41 +0,0 @@
//
// Created by light on 19-12-16.
//
#include <complex> // std::complex
#include <iostream> // std::cout/endl
#include <unordered_map> // std::unordered_map
#include <unordered_set> // std::unordered_set
#include "../container1/output_container.h"
using namespace std;
namespace std {
template <typename T>
struct hash<complex<T>> {
size_t
operator()(const complex<T>& v) const
noexcept
{
hash<T> h;
return h(v.real()) + h(v.imag());
}
};
} // namespace std
int main()
{
unordered_set<int> s{
1, 1, 2, 3, 5, 8, 13, 21
};
cout << s << endl;
unordered_map<complex<double>,
double>
umc{{{1.0, 1.0}, 1.4142},
{{3.0, 4.0}, 5.0}};
cout << umc << endl;
}

View File

@@ -1,34 +0,0 @@
//
// Created by light on 20-1-11.
//
#include <iostream>
using namespace std;
struct adder {
adder(int n) : n_(n) {}
int operator()(int x) const {
return x + n_;
}
private:
int n_;
};
int main() {
auto add_2 = adder(2);
// x+2
cout << add_2(3) << endl;
auto t = bind1st(plus<int>(), 2);
cout << t(1) << endl;
// 上述的C++98
binder2nd<plus<int> > a2(plus<int>(), 2);
cout << a2(3) << endl;
cout << [](int x) { return x * x; }(3) << endl;
return 0;
// lambda表达式默认就是constexpr函数
}

View File

@@ -1,64 +0,0 @@
//
// Created by light on 20-1-11.
//
#include <chrono>
#include <iostream>
#include <sstream>
#include <thread>
using namespace std;
int get_count() {
static int count = 0;
return ++count;
}
class task {
public:
task(int data) : data_(data) {}
/**
* this 标明按引用捕获外围对象(针对 lambda 表达式定义出现在一个非静态类成员内的情况);
* 注意默认捕获符 = 和 & 号可以自动捕获 this并且在 C++20 之前,在 = 后写 this 会导致出错)
* 本例子两次都按照第二次输出(this_thread::sleep_for(100ms);
* this 标明按引用捕获外围对象
*
*
* *this 标明按值捕获外围对象(针对 lambda 表达式定义出现在一个非静态类成员内的情况C++17 新增语法)
* 本例子正常输出
*/
auto lazy_launch() {
return
[*this, count = get_count()]()
mutable {
ostringstream oss;
oss << "Done work " << data_
<< " (No. " << count
<< ") in thread "
<< this_thread::get_id()
<< '\n';
msg_ = oss.str();
calculate();
};
}
void calculate() {
this_thread::sleep_for(100ms);
cout << msg_;
}
private:
int data_;
string msg_;
};
int main() {
auto t = task{37};
thread t1{t.lazy_launch()};
thread t2{t.lazy_launch()};
t1.join();
t2.join();
}

View File

@@ -1,32 +0,0 @@
//
// Created by light on 20-1-11.
//
#include <map>
#include <iostream>
#include <functional>
using namespace std;
int main() {
map<string, function<int(int, int)>>
op_dict{
{"+",
[](int x, int y) {
return x + y;
}},
{"-",
[](int x, int y) {
return x - y;
}},
{"*",
[](int x, int y) {
return x * y;
}},
{"/",
[](int x, int y) {
return x / y;
}},
};
}

View File

@@ -1,13 +0,0 @@
//
// Created by light on 19-12-25.
//
#include <iostream>
#include <cassert>
int main() {
const int alignment=5;
assert((alignment & (alignment - 1)) == 0);
static_assert((alignment & (alignment - 1)) == 0, "Alignment must be power of two");
return 0;
}

View File

@@ -1,18 +0,0 @@
//
// Created by light on 19-12-25.
//
class myFun {
public:
myFun() = default;
myFun(const myFun &) = default;
myFun &operator=(const myFun &) = default;
myFun(myFun &&) = delete;
myFun &operator=(myFun &&) = delete;
~myFun() = default;
};

View File

@@ -1,81 +0,0 @@
//
// Created by light on 19-12-25.
//
#include <chrono>
#include <complex>
#include <iostream>
#include <string>
#include <thread>
#include <bitset>
using namespace std::literals::chrono_literals;
using namespace std::literals::string_literals;
using namespace std::literals::complex_literals;
struct length {
double value;
enum unit {
metre,
kilometre,
millimetre,
centimetre,
inch,
foot,
yard,
mile,
};
static constexpr double factors[] =
{1.0, 1000.0, 1e-3,
1e-2, 0.0254, 0.3048,
0.9144, 1609.344};
explicit length(double v,
unit u = metre) {
value = v * factors[u];
}
};
length operator+(length lhs,
length rhs) {
return length(lhs.value +
rhs.value);
}
length operator "" _m(long double v) { return length(v, length::metre); }
length operator "" _cm(long double v) { return length(v, length::centimetre); }
// 可能有其他运算符
int main() {
std::cout << "i * i = " << 1i * 1i << std::endl;
std::cout << "Waiting for 500ms" << std::endl;
std::this_thread::sleep_for(500ms);
std::cout << "Hello world"s.substr(0, 5) << std::endl;
length l1 = length(1.0, length::metre);
length l2 = length(1.0, length::centimetre);
std::cout << l2.value << std::endl;
std::cout << (l1 + l2).value << std::endl;
// 1.0_m + 10.0_cm
std::cout << (1.0_m + 1.0_cm).value << std::endl;
// 二进制字面量
unsigned mask = 0b1101;
// 以十进制打印
std::cout << mask << std::endl;
// 打印二进制字面量
std::cout << std::bitset<4>(mask) << std::endl;
// 数字分隔符
unsigned mk = 0b111'000'000;
double pi = 3.141'5926;
return 0;
}

View File

@@ -1,30 +0,0 @@
//
// Created by light on 19-12-25.
//
class A {
public:
virtual void foo();
virtual void bar();
void foobar();
};
class B : public A {
public:
void foo() override; // OK
void bar() override final; // OK
//void foobar() override;
// 非虚函数不能 override
};
class C final : public B {
public:
void foo() override; // OK
//void bar() override;
// final 函数不可 override
};
class D : public C {
// 错误final 类不可派生
};

View File

@@ -1,97 +0,0 @@
//
// Created by light on 19-12-23.
//
#include <iostream>
#include <vector>
#include <string>
struct Test {
Test()
{
//std::cout << "construct a Test object" << std::endl;
}
Test(const Test&)
{
std::cout << "copy construct a Test object" << std::endl;
}
Test& operator=(const Test &t)
{
std::cout << "copy assignment a Test object" << std::endl;
return *this;
}
Test(Test&& t)
{
std::cout << "move construct a Test object" << std::endl;
}
Test& operator=(Test &&t)
{
std::cout << "move assignment a Test object" << std::endl;
return *this;
}
~Test()
{
//std::cout << "destruct a Test object" << std::endl;
}
};
Test getTest()
{
// anonymous object
return Test();
}
Test getTestWithName()
{
// named return value
Test temp;
return temp;
}
/**
* 1.copy construct本身在RVO和NRVO两种情况下被优化了如果再加上move反而画蛇添足。
* 2.加入了move assignment后默认是调用move assignment而不是copy assignment可以将move assignment注释后测试。
* 3.对于RVO和NRVO来说construction的情况编译器优化得比较好了加入move语义主要是对于assignment有比较大影响
*/
int main()
{
std::cout << "==== common case ====" << std::endl;
Test o1;
std::cout << "---- Test copy construct: " << std::endl;
Test o2(o1); // two ways for copy construct
Test o3 = o1;
std::cout << "---- Test move construct: " << std::endl;
Test o4(std::move(o3));
std::cout << "---- Test assignment: " << std::endl;
o2 = o1;
std::cout << "---- Test move assignment: " << std::endl;
Test o5; o5 = std::move(o4);
std::cout << "\n==== test for rvo ===" << std::endl;
std::cout << "---- Test rvo for copy construct: " << std::endl;
Test obj11(getTest());
Test obj1 = getTest();
std::cout << "---- Test rvo for move construct: " << std::endl;
Test obj12(std::move(getTest()));
std::cout << "---- Test rvo for assignment: " << std::endl;
Test obj2; obj2 = getTest();
std::cout << "---- Test rvo move assignment: " << std::endl;
Test obj5; obj5 = std::move(getTest());
std::cout << "\n==== test for nrvo ===" << std::endl;
std::cout << "---- Test nrvo for copy construct: " << std::endl;
Test obj33(getTestWithName());
Test obj3 = getTestWithName();
std::cout << "---- Test nrvo for move construct: " << std::endl;
Test obj34(std::move(getTestWithName()));
std::cout << "---- Test nrvo for assignment: " << std::endl;
Test obj4; obj4 = getTestWithName();
std::cout << "---- Test nrvo move assignment: " << std::endl;
Test obj6; obj6 = std::move(getTestWithName());
return 0;
}

View File

@@ -1,49 +0,0 @@
//
// Created by light on 19-12-22.
//
// rvo example
#include <iostream>
using namespace std;
// Can copy and move
class A {
public:
A() { cout << "Create A\n"; }
~A() { cout << "Destroy A\n"; }
A(const A &) { cout << "Copy A\n"; }
A(A &&) { cout << "Move A\n"; }
A& operator=(const A&a)
{
std::cout << "copy assignment" << std::endl;
return *this;
}
A& operator=(A &&a) {
cout << "move assignment\n";
return *this;
}
};
// 编译器可以优化 返回值移动出去
A getA_unnamed() {
return A();
}
int main() {
// cout<<"构造"<<endl;
// auto a = getA_unnamed();
cout<<"赋值"<<endl;
A aa;
aa=getA_unnamed();
// aa=std::move(getA_unnamed());
}

View File

@@ -1,48 +0,0 @@
//
// Created by light on 19-12-22.
//
// nrvo example
#include <iostream>
using namespace std;
// Can copy and move
class A {
public:
A() { cout << "Create A\n"; }
~A() { cout << "Destroy A\n"; }
A(const A &) { cout << "Copy A\n"; }
A(A &&) { cout << "Move A\n"; }
A& operator=(const A&a)
{
std::cout << "copy assignment" << std::endl;
return *this;
}
A& operator=(A &&a) {
cout << "move assignment\n";
return *this;
}
};
// 编译器可以优化 返回值移动出去
A getA_named() {
A a;
return a;
}
int main() {
// cout<<"拷贝"<<endl;
// auto a = getA_named();
cout<<"赋值"<<endl;
A aa;
aa=getA_named();
}

View File

@@ -1,51 +0,0 @@
//
// Created by light on 19-12-22.
//
#include <iostream>
using namespace std;
// Can copy and move
class A {
public:
A() { cout << "Create A\n"; }
~A() { cout << "Destroy A\n"; }
A(const A &) { cout << "Copy A\n"; }
A(A &&) { cout << "Move A\n"; }
A& operator=(const A&a)
{
std::cout << "copy assignment" << std::endl;
return *this;
}
A& operator=(A &&a) {
cout << "move assignment\n";
return *this;
}
};
// 编译器无法优化
A getA_duang() {
A a1;
A a2;
if (rand() > 42) {
return a1;
}
else {
return a2;
}
}
int main() {
// cout<<"拷贝"<<endl;
// auto a = getA_duang();
cout<<"赋值"<<endl;
A aa;
aa=getA_duang();
}

View File

@@ -1,35 +0,0 @@
//
// Created by light on 19-12-22.
//
#include <iostream>
using namespace std;
// Can copy and move
class A {
public:
A() { cout << "Create A\n"; }
~A() { cout << "Destroy A\n"; }
A(const A &) { cout << "Copy A\n"; }
A(A&&)= delete;
};
A getA_duang() {
A a1;
A a2;
if (rand() > 42) {
return a1;
}
else {
return a2;
}
}
int main() {
auto a = getA_duang();
}

View File

@@ -1,31 +0,0 @@
//
// Created by light on 19-12-22.
//
#include <iostream>
using namespace std;
// Can copy and move
class A {
public:
A() { cout << "Create A\n"; }
~A() { cout << "Destroy A\n"; }
// A(const A &) { cout << "Copy A\n"; }
//
// A(A &&) { cout << "Move A\n"; }
A(const A&&)= delete;
A(A&&)= delete;
};
A getA_unnamed() {
return A();
}
int main() {
auto a = getA_unnamed();
}

View File

@@ -1,120 +0,0 @@
//
// Created by light on 19-12-9.
//
#include "../RAII/shape.h"
template<typename T>
class auto_ptr {
public:
explicit auto_ptr(
T *ptr = nullptr) noexcept
: ptr_(ptr) {}
~auto_ptr() noexcept {
delete ptr_;
}
T &operator*() const noexcept { return *ptr_; }
T *operator->() const noexcept { return ptr_; }
operator bool() const noexcept { return ptr_; }
T *get() const noexcept { return ptr_; }
// 拷贝构造,被复制放释放原来指针的所有权,交给复制方 始终只有一个对象管理一块空间
auto_ptr(auto_ptr &other) noexcept {
ptr_ = other.release();
}
// copy and swap 始终只有一个对象有管理这块空间的权限
auto_ptr &operator=(auto_ptr &rhs) noexcept {
// auto_ptr tmp(rhs.release());
// tmp.swap(*this);
// s上述两行等价于下面一行
auto_ptr(rhs.release()).swap(*this);
return *this;
}
// 原来的指针释放所有权
T *release() noexcept {
T *ptr = ptr_;
ptr_ = nullptr;
return ptr;
}
void swap(auto_ptr &rhs) noexcept {
using std::swap;
swap(ptr_, rhs.ptr_); // 转移指针所有权
}
private:
T *ptr_;
};
template<typename T>
void swap(auto_ptr<T> &lhs, auto_ptr<T> &rhs) noexcept {
lhs.swap(rhs);
}
template<class T>
class scoped_ptr // noncopyable
{
public:
explicit scoped_ptr(T *ptr = 0) noexcept : ptr_(ptr) {
}
~scoped_ptr() noexcept {
delete ptr_;
}
void reset(T *p = 0) noexcept {
scoped_ptr(p).swap(*this);
}
T &operator*() const noexcept {
return *ptr_;
}
T *operator->() const noexcept {
return ptr_;
}
T *get() const noexcept {
return ptr_;
}
void swap(scoped_ptr &rhs) noexcept {
using std::swap;
swap(ptr_, rhs.ptr_);
}
private:
T *ptr_;
scoped_ptr(scoped_ptr const &);
scoped_ptr &operator=(scoped_ptr const &);
};
template<typename T>
void swap(scoped_ptr<T> &lhs, scoped_ptr<T> &rhs) noexcept {
lhs.swap(rhs);
}
int main() {
auto_ptr<shape> ptr1{create_shape(shape_type::circle)};
auto_ptr<shape> ptr2{ptr1};
if (ptr1.get() == nullptr && ptr2.get())
cout << "拷贝构造ptr1释放了所有权,ptr2获得了所有权" << endl;
ptr1 = ptr1;
auto_ptr<shape> ptr3{create_shape(shape_type::rectangle)};
ptr1 = ptr3;
if (ptr3.get() == nullptr && ptr1.get())
cout << "赋值操作:始终只有一个对象管理一个区块!ptr3释放了所有权,ptr1获得了所有权" << endl;
scoped_ptr<shape> sptr1{create_shape(shape_type::circle)};
// scoped_ptr<shape> sptr2{sptr1}; // error 不可拷贝
}

View File

@@ -1,232 +0,0 @@
//
// Created by light on 19-12-12.
//
#include "../RAII/shape.h"
class shared_count {
public:
shared_count() : count_(1) {
}
// 增加计数
void add_count() {
++count_;
}
// 减少计数
long reduce_count() {
return --count_;
}
// 获取当前计数
long get_count() const {
return count_;
}
private:
long count_;
};
template<typename T>
class shared_ptr {
public:
explicit shared_ptr(
T *ptr = nullptr) noexcept
: ptr_(ptr) {
if (ptr) {
shared_count_ = new shared_count();
}
}
// 实现强制类型转换需要的构造函数
template<typename U>
shared_ptr(const shared_ptr<U> &other, T *ptr) noexcept {
ptr_ = ptr;
if (ptr_) {
other.shared_count_->add_count();
shared_count_ = other.shared_count_;
}
}
~shared_ptr() noexcept {
// 最后一个shared_ptr再去删除对象与共享计数
// ptr_不为空且此时共享计数减为0的时候,再去删除
if (ptr_ && !shared_count_->reduce_count()) {
delete ptr_;
delete shared_count_;
}
}
T &operator*() const noexcept { return *ptr_; }
T *operator->() const noexcept { return ptr_; }
operator bool() const noexcept { return ptr_; }
T *get() const noexcept { return ptr_; }
// 带模板的拷贝与移动构造函数 模板的各个实例间并不天然就有 friend 关系,因而不能互访私有成员 ptr_ 和 shared_count_。
// 需要下面显示声明
template<typename U>
friend
class shared_ptr;
template<typename U>
shared_ptr(const shared_ptr<U> &other) noexcept {
// cout << "调用了带模板的拷贝构造!" << endl;
ptr_ = other.ptr_;
if (ptr_) {
other.shared_count_
->add_count();
shared_count_ =
other.shared_count_;
}
}
template<typename U>
shared_ptr(shared_ptr<U> &&other) noexcept {
// cout << "调用了带模板的移动构造!" << endl;
ptr_ = other.ptr_;
if (ptr_) {
shared_count_ =
other.shared_count_;
other.ptr_ = nullptr;
other.shared_count_ = nullptr;
}
}
// copy and swap 始终只有一个对象有管理这块空间的权限
shared_ptr &operator=(shared_ptr rhs) noexcept {
rhs.swap(*this);
return *this;
}
void swap(shared_ptr &rhs) noexcept {
using std::swap;
swap(ptr_, rhs.ptr_);
swap(shared_count_, rhs.shared_count_);
}
long use_count() const noexcept {
if (ptr_) {
return shared_count_->get_count();
} else {
return 0;
}
}
private:
T *ptr_;
shared_count *shared_count_;
};
template<typename T>
void swap(shared_ptr<T> &lhs, shared_ptr<T> &rhs) noexcept {
lhs.swap(rhs);
}
template<typename T, typename U>
shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U> &other) noexcept {
T *ptr = dynamic_cast<T *>(other.get());
return shared_ptr<T>(other, ptr);
}
template<typename T, typename U>
shared_ptr<T> static_pointer_cast(const shared_ptr<U> &other) noexcept {
T *ptr = static_cast<T *>(other.get());
return shared_ptr<T>(other, ptr);
}
template<typename T, typename U>
shared_ptr<T> const_pointer_cast(
const shared_ptr<U> &other) noexcept {
T *ptr = const_cast<T *>(other.get());
return shared_ptr<T>(other, ptr);
}
template<typename T, typename U>
shared_ptr<T> reinterpret_pointer_cast(
const shared_ptr<U> &other) noexcept {
T *ptr = reinterpret_cast<T *>(other.get());
return shared_ptr<T>(other, ptr);
}
int main() {
shared_ptr<circle> ptr1(new circle());
cout << "use count of ptr1 is " << ptr1.use_count() << endl;
shared_ptr<shape> ptr2, ptr3;
cout << "use count of ptr2 was " << ptr2.use_count() << endl;
ptr2 = ptr1; // shared_ptr<circle>隐式转换shared_ptr<shape> 调用带模板的拷贝构造
// cout<<"======="<<endl;
// ptr3 = ptr2; // 调用的是编译器生成的默认拷贝构造 所以引用计数不会增加 ptr3=ptr2
// cout<<"======="<<endl;
ptr3 = ptr1;
cout << "此时3个shared_ptr指向同一个资源" << endl;
cout << "use count of ptr1 is now " << ptr1.use_count() << endl;
cout << "use count of ptr2 is now " << ptr2.use_count() << endl;
cout << "use count of ptr3 is now " << ptr3.use_count() << endl;
if (ptr1)
cout << "ptr1 is not empty" << endl;
// 会先调用赋值函数,由编译器决定调用的是拷贝构造还是移动构造,造出一个新的临时对象出来,临时对象会在跳出作用域后被析构掉。
// 在析构函数中,会先判断该临时对象的是否指向资源,如果没有,析构结束。否则,对引用计数减1,判断引用计数是否为0,如果为0,删除共享引用计数指针,否则不操作。
cout << "此时2个shared_ptr指向同一个资源" << endl;
ptr2 = std::move(ptr1);
if (!ptr1 && ptr2) { // 调用的是bool重载操作符
cout << "ptr1 move to ptr2" << endl;
cout << "use count of ptr1 is now " << ptr1.use_count() << endl;
cout << "use count of ptr2 is now " << ptr2.use_count() << endl;
cout << "use count of ptr3 is now " << ptr3.use_count() << endl;
}
// shape* -> circle* 使用dynamic_cast转换后,指针为空.此时资源还是被dptr2拥有,dptr1为0
shared_ptr<shape> dptr2(new shape);
shared_ptr<circle> dptr1 = dynamic_pointer_cast<circle>(dptr2); // 基类转子类
cout << "use count of dptr1 is now " << dptr1.use_count() << endl; // 0
cout << "use count of dptr2 is now " << dptr2.use_count() << endl; // 1
// circle* -> circle* 使用dynamic_cast转换后,指针不为空,此时资源被两者共同使用,引用计数为2
shared_ptr<shape> dptr3(new circle);
// shared_ptr<circle> dptr3(new circle); // 上面或者当前行,后面输出一样!
shared_ptr<circle> dptr1_1 = dynamic_pointer_cast<circle>(dptr3); // 基类转子类
cout << "use count of dptr1_1 is now " << dptr1_1.use_count() << endl; // 2
cout << "use count of dptr3 is now " << dptr3.use_count() << endl; // 2
// circle* -> circle* 使用dynamic_cast转换后,指针不为空,此时资源被两者共同使用,引用计数为2
shared_ptr<circle> dptr3_1(new circle);
shared_ptr<shape> dptr2_1 = dynamic_pointer_cast<shape>(dptr3_1); // 子类转基类 上行转换,安全!
cout << "use count of dptr2_1 is now " << dptr2_1.use_count() << endl; // 2
cout << "use count of dptr3_1 is now " << dptr3_1.use_count() << endl; // 2
// shape* -> circle* 使用static_cast转换后,指针为空 与dynamic_cast相比,不安全
shared_ptr<shape> sptr2(new shape);
shared_ptr<circle> sptr1 = static_pointer_cast<circle>(sptr2); // 基类转子类
cout << "use count of sptr1 is now " << dptr1.use_count() << endl; // 0
cout << "use count of sptr2 is now " << dptr2.use_count() << endl; // 1
// circle* -> circle* 使用dynamic_cast转换后,指针不为空,此时资源被两者共同使用,引用计数为2
shared_ptr<shape> sptr3(new circle);
// shared_ptr<circle> sptr3(new circle); // 上面或者当前行,后面输出一样!
shared_ptr<circle> sptr1_1 = static_pointer_cast<circle>(sptr3); // 基类转子类
cout << "use count of sptr1_1 is now " << sptr1_1.use_count() << endl; // 2
cout << "use count of sptr3 is now " << sptr3.use_count() << endl; // 2
// circle* -> circle* 使用static_cast转换后,指针不为空,此时资源被两者共同使用,引用计数为2 等价于dynamic_cast
shared_ptr<circle> sptr3_1(new circle);
shared_ptr<shape> sptr2_1 = static_pointer_cast<shape>(sptr3_1); // 子类转基类 上行转换,安全!
cout << "use count of sptr2_1 is now " << sptr2_1.use_count() << endl; // 2
cout << "use count of sptr3_1 is now " << sptr3_1.use_count() << endl; // 2
shared_ptr<const int> constV(new int);
shared_ptr<int> s = const_pointer_cast<int>(constV);
*s =10;
int a = reinterpret_pointer_cast<int>(s);
cout<<a<<endl;
}

View File

@@ -1,79 +0,0 @@
//
// Created by light on 19-12-12.
//
#include "../RAII/shape.h"
template<typename T>
class unique_ptr {
public:
explicit unique_ptr(
T *ptr = nullptr) noexcept
: ptr_(ptr) {}
~unique_ptr() noexcept {
delete ptr_;
}
T &operator*() const noexcept { return *ptr_; }
T *operator->() const noexcept { return ptr_; }
operator bool() const noexcept { return ptr_; }
T *get() const noexcept { return ptr_; }
unique_ptr(unique_ptr &&other) noexcept {
cout << "move ctor" << endl;
ptr_ = other.release();
}
template<typename U>
unique_ptr(unique_ptr<U> &&other) noexcept {
cout << "U move ctor" << endl;
ptr_ = other.release();
}
// copy and swap 始终只有一个对象有管理这块空间的权限
unique_ptr &operator=(unique_ptr rhs) noexcept {
rhs.swap(*this);
return *this;
}
// 原来的指针释放所有权
T *release() noexcept {
T *ptr = ptr_;
ptr_ = nullptr;
return ptr;
}
void swap(unique_ptr &rhs) noexcept {
using std::swap;
swap(ptr_, rhs.ptr_); // 转移指针所有权
}
private:
T *ptr_;
};
template<typename T>
void swap(unique_ptr<T> &lhs, unique_ptr<T> &rhs) {
lhs.swap(rhs);
}
int main() {
unique_ptr<shape> ptr1{create_shape(shape_type::circle)};
// unique_ptr<shape> ptr2{ptr1}; // error
unique_ptr<shape> ptr2_2{std::move(ptr1)}; // ok
if (ptr2_2.get() != nullptr && ptr1.get() == nullptr)
ptr2_2.get()->print();
unique_ptr<shape> ptr3{create_shape(shape_type::rectangle)};
// ptr1 = ptr3; // error
ptr3 = std::move(ptr1); // ok
// unique_ptr<circle> cl{create_shape(shape_type::circle)}; // error 因为create_shape返回的是shape 不能基类转子类
unique_ptr<circle> cl{new circle()};
unique_ptr<shape> ptr5(std::move(cl)); // ok unique<circle>转unique<circle>
}

View File

@@ -1,72 +0,0 @@
//
// Created by light on 19-12-12.
//
#include "../RAII/shape.h"
template<typename T>
class unique_ptr {
public:
explicit unique_ptr(
T *ptr = nullptr) noexcept
: ptr_(ptr) {}
~unique_ptr() noexcept {
delete ptr_;
}
T &operator*() const noexcept { return *ptr_; }
T *operator->() const noexcept { return ptr_; }
operator bool() const noexcept { return ptr_; }
T *get() const noexcept { return ptr_; }
template<typename U>
unique_ptr(unique_ptr<U> &&other) noexcept {
cout << "U move ctor" << endl;
ptr_ = other.release();
}
// copy and swap 始终只有一个对象有管理这块空间的权限
unique_ptr &operator=(unique_ptr rhs) noexcept {
rhs.swap(*this);
return *this;
}
// 原来的指针释放所有权
T *release() noexcept {
T *ptr = ptr_;
ptr_ = nullptr;
return ptr;
}
void swap(unique_ptr &rhs) noexcept {
using std::swap;
swap(ptr_, rhs.ptr_); // 转移指针所有权
}
private:
T *ptr_;
};
int main() {
unique_ptr<shape> ptr1{create_shape(shape_type::circle)};
unique_ptr<shape> ptr2{ptr1}; // 由于带模板的移动构造函数引发编译器会默认生成拷贝构造
if (ptr1.get() != nullptr) // bitwise copy 此时ptr1不为NULL
ptr2.get()->print();
unique_ptr<shape> ptr2_2{std::move(ptr1)}; // 调用的是默认的移动构造,而不是带模板的移动构造 bitwise move
if (ptr2_2.get() != nullptr && ptr1.get() != nullptr) // ptr1 不为空
ptr2_2.get()->print();
unique_ptr<shape> ptr3{create_shape(shape_type::rectangle)};
ptr1 = ptr3; // ok 根据形参先调用默认拷贝,再调用拷贝赋值
ptr3 = std::move(ptr1); // ok 根据形参先调用默认移动构造,而不是带参数的移动构造,再调用移动赋值
unique_ptr<shape> ptr4(std::move(new circle)); // ok 调用带模板的移动构造
}

View File

@@ -0,0 +1,21 @@
# please run `bazel run //learn_class/modern_cpp_30/RAII:stack`
# please run `bazel run //learn_class/modern_cpp_30/RAII:heap`
# please run `bazel run //learn_class/modern_cpp_30/RAII:RAII`
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "stack",
srcs = ["stack.cpp"],
copts = ["-std=c++11"],
)
cc_binary(
name = "heap",
srcs = ["heap.cpp"],
copts = ["-std=c++11"],
)
cc_binary(
name = "RAII",
srcs = ["RAII.cpp"],
copts = ["-std=c++11"],
)

View File

@@ -0,0 +1,82 @@
#include <fstream>
#include <iostream>
#include <mutex>
using namespace std;
enum class shape_type {
circle,
triangle,
rectangle,
};
class shape {
public:
shape() { cout << "shape" << endl; }
virtual void print() { cout << "I am shape" << endl; }
virtual ~shape() {}
};
class circle : public shape {
public:
circle() { cout << "circle" << endl; }
void print() { cout << "I am circle" << endl; }
};
class triangle : public shape {
public:
triangle() { cout << "triangle" << endl; }
void print() { cout << "I am triangle" << endl; }
};
class rectangle : public shape {
public:
rectangle() { cout << "rectangle" << endl; }
void print() { cout << "I am rectangle" << endl; }
};
// 利用多态 上转 如果返回值为shape,会存在对象切片问题。
shape *create_shape(shape_type type) {
switch (type) {
case shape_type::circle:
return new circle();
case shape_type::triangle:
return new triangle();
case shape_type::rectangle:
return new rectangle();
}
}
class shape_wrapper {
public:
explicit shape_wrapper(shape *ptr = nullptr) : ptr_(ptr) {}
~shape_wrapper() { delete ptr_; }
shape *get() const { return ptr_; }
private:
shape *ptr_;
};
void foo() {
shape_wrapper ptr(create_shape(shape_type::circle));
ptr.get()->print();
}
int main() {
// 第一种方式
shape *sp = create_shape(shape_type::circle);
sp->print();
delete sp;
// 第二种方式
foo();
return 0;
}

View File

@@ -0,0 +1,35 @@
#include <iostream>
using namespace std;
class bar {};
// java 程序员风格
void foo() {
cout << "method 1" << endl;
bar *ptr = new bar();
delete ptr;
}
bar *make_bar() {
bar *ptr = nullptr;
try {
ptr = new bar();
} catch (...) {
delete ptr;
throw;
}
return ptr;
}
// 独立出函数 分配和释放不在一个函数里
void foo1() {
cout << "method 2" << endl;
bar *ptr = make_bar();
delete ptr;
}
int main() {
foo();
foo1();
return 0;
}

View File

@@ -0,0 +1,23 @@
//
// Created by light on 19-12-9.
//
#include <iostream>
class Obj {
public:
Obj() { puts("Obj()"); }
~Obj() { puts("~Obj()"); }
};
void foo(int n) {
Obj obj;
if (n == 42)
throw "life, the universe and everything";
}
// 不管是否发生了异常obj 的析构函数都会得到执行。
int main() {
try {
foo(41);
foo(42);
} catch (const char *s) {
puts(s);
}
}

View File

@@ -0,0 +1,33 @@
//
// Created by light on 20-1-5.
//
#include <iostream>
using namespace std;
template <typename T> class IsClassT {
private:
typedef char One;
typedef struct {
char a[2];
} Two;
template <typename C> static One test(int C::*);
// Will be chosen if T is anything except a class.
template <typename C> static Two test(...);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
struct A {};
int main() {
// 0不能转换为int int::*因为int不是类所以它不能有成员指针。
cout << IsClassT<int>::Yes << endl;
cout << IsClassT<A>::Yes << endl;
return 0;
}

View File

@@ -0,0 +1,27 @@
# please run `bazel run //learn_class/modern_cpp_30/compilercompute:IF`
# please run `bazel run //learn_class/modern_cpp_30/compilercompute:factorial`
# please run `bazel run //learn_class/modern_cpp_30/compilercompute:fmap`
# please run `bazel run //learn_class/modern_cpp_30/compilercompute:WhileLoop`
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "IF",
srcs = ["IF.cpp"],
copts = ["-std=c++17"],
)
cc_binary(
name = "factorial",
srcs = ["factorial.cpp"],
copts = ["-std=c++17"],
)
cc_binary(
name = "fmap",
srcs = ["fmap.cpp"],
copts = ["-std=c++17"],
)
cc_binary(
name = "WhileLoop",
srcs = ["WhileLoop.cpp"],
copts = ["-std=c++17"],
)

View File

@@ -0,0 +1,43 @@
//
// Created by light on 19-12-28.
//
#include <iostream>
using namespace std;
// 使用template实现IF条件判断
template <bool cond, typename Then, typename Else> struct IF;
template <typename Then, typename Else> struct IF<true, Then, Else> {
typedef Then result;
};
template <typename Then, typename Else> struct IF<false, Then, Else> {
typedef Else result;
};
// 判断奇数与偶数
template <int N> struct isEven {
static const auto RES = IF<N & 1 == 0, true_type, false_type>::result::value;
};
template <int nums1, int nums2> struct Add_ {
static const int value = nums1 + nums2;
};
template <int nums1, int nums2> struct Sub_ {
static const int value = nums1 - nums2;
};
// 加减
template <bool cond, int nums1, int nums2> struct addSub {
static const auto RES =
IF<cond, Add_<nums1, nums2>, Sub_<nums1, nums2>>::result::value;
};
int main() {
cout << isEven<10>::RES << endl;
cout << addSub<true, 10, 2>::RES << endl;
}

View File

@@ -0,0 +1,57 @@
//
// Created by light on 20-1-5.
//
#include <iostream>
using namespace std;
// 使用template实现while循环
template <bool condition, typename Body> struct WhileLoop;
template <typename Body> struct WhileLoop<true, Body> {
typedef
typename WhileLoop<Body::cond_value, typename Body::next_type>::type type;
};
template <typename Body> struct WhileLoop<false, Body> {
typedef typename Body::res_type type;
};
template <typename Body> struct While {
typedef typename WhileLoop<Body::cond_value, Body>::type type;
};
template <typename Body> using While_t = WhileLoop<Body::cond_value, Body>;
namespace my {
template <class T, T v> struct integral_constant {
static const T value = v;
typedef T value_type;
typedef integral_constant<T, v> type;
};
} // namespace my
template <int result, int n> struct SumLoop {
// 循环的条件
static const bool cond_value = n != 0;
// 循环后的结果
static const int res_value = result;
// 循环时的状态
typedef my::integral_constant<int, res_value> res_type;
// 循环执行一次时的状态
typedef SumLoop<result + n, n - 1> next_type;
};
template <int n> struct Sum { typedef SumLoop<0, n> type; };
template <int n> using Sum_t = SumLoop<0, n>;
int main() {
cout << While<Sum<6>::type>::type::value << endl;
cout << While_t<Sum_t<6>>::type::value << endl;
return 0;
}

View File

@@ -0,0 +1,20 @@
//
// Created by light on 19-12-28.
//
#include <iostream>
using namespace std;
template <int n> struct factorial {
static_assert(n >= 0, "Arg must be non-negative");
static const int value = n * factorial<n - 1>::value;
};
template <> struct factorial<0> { static const int value = 1; };
int main() {
printf("%d\n", factorial<10>::value);
return 0;
}

View File

@@ -0,0 +1,34 @@
//
// Created by light on 20-1-5.
//
#include <iostream>
#include <vector>
using namespace std;
template <template <typename, typename> class OutContainer = vector, typename F,
class R>
auto fmap(F &&f, R &&inputs) {
typedef decay_t<decltype(f(*inputs.begin()))> result_type;
OutContainer<result_type, allocator<result_type>> result;
for (auto &&item : inputs) {
result.push_back(f(item));
}
return result;
}
// 对每一个数进行加1操作
int add_1(int x) { return x + 1; }
int main() {
vector<int> v{1, 2, 3, 4, 5};
auto result = fmap(add_1, v);
for (auto item : result)
cout << item << " ";
cout << endl;
return 0;
}

View File

@@ -0,0 +1,9 @@
# please run `bazel run //learn_class/modern_cpp_30/compilerpoly:template`
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "template",
srcs = ["template.cpp"],
copts = ["-std=c++17"],
)

View File

@@ -0,0 +1,30 @@
# please run `bazel run //learn_class/modern_cpp_30/constexpr:test3`
# please run `bazel run //learn_class/modern_cpp_30/constexpr:newconstexpr`
# please run `bazel run //learn_class/modern_cpp_30/constexpr:container`
# please run `bazel run //learn_class/modern_cpp_30/constexpr:sqrt`
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "test3",
srcs = ["test3.cpp"],
copts = ["-std=c++17"],
)
cc_binary(
name = "newconstexpr",
srcs = ["newconstexpr.cpp"],
copts = ["-std=c++17"],
)
cc_binary(
name = "container",
srcs = ["container.cpp"],
copts = ["-std=c++17"],
deps = [
"//learn_class/modern_cpp_30/container1:output_container",
],
)
cc_binary(
name = "sqrt",
srcs = ["sqrt.cpp"],
copts = ["-std=c++17"],
)

View File

@@ -0,0 +1,32 @@
//
// Created by light on 19-12-16.
//
#include "../container1/output_container.h"
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
int main() {
map<int, int> mp{{1, 1}, {2, 4}, {3, 9}};
cout << mp << endl;
vector<vector<int>> vv{{1, 1}, {2, 4}, {3, 9}};
cout << vv << endl;
pair<int, int> p{1, 2};
cout << p << endl;
set<int> s{1, 2, 3};
cout << s << endl;
vector<char> v{'a', 'b'};
cout << v << endl;
set<char *> vs{"a", "b"};
cout << vs << endl;
map<int, char *> mm{{1, "23"}, {2, "234hi"}};
cout << mm << endl;
}

View File

@@ -0,0 +1,73 @@
//
// Created by light on 20-1-7.
//
#include <array>
#include <iostream>
#include <vector>
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 <class T>
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<int> v;
v.push_back(magic::number); // undefined reference to `magic::number'
std::cout << v[0] << std::endl;
// 不重要的析构
std::cout << is_trivially_destructible_v<A> << std::endl;
std::cout << is_trivially_destructible_v<B> << 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<int, 5> 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';
}

View File

@@ -0,0 +1,134 @@
//
// Created by light on 20-1-8.
//
#ifndef MORDEN_C_OUTPUT_CONTAINER_H
#define MORDEN_C_OUTPUT_CONTAINER_H
#include <ostream> // std::ostream
#include <type_traits> // std::false_type/true_type/decay_t/is_same_v
#include <utility> // std::declval/pair
// 检测是否是pair
template <typename T> struct is_pair : std::false_type {};
template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type {};
template <typename T> inline constexpr bool is_pair_v = is_pair<T>::value;
// 检测是否可以直接输出
template <typename T> struct has_output_function {
template <class U>
static auto output(U *ptr)
-> decltype(std::declval<std::ostream &>() << *ptr, std::true_type());
template <class U> static std::false_type output(...);
static constexpr bool value = decltype(output<T>(nullptr))::value;
};
template <typename T>
inline constexpr bool has_output_function_v = has_output_function<T>::value;
enum CHARS {
ORD, // 其他类型
CHAR, // char 类型
STRING // string 类型
};
template <typename T> int ischarOrString(T &elem) {
using std::decay_t;
using std::is_same_v;
using element_type = decay_t<decltype(elem)>;
constexpr bool is_char_v = is_same_v<element_type, char>;
constexpr bool is_string_v = is_same_v<element_type, char *> ||
is_same_v<element_type, const char *> ||
is_same_v<element_type, std::string>;
if (is_char_v)
return CHAR;
else if (is_string_v)
return STRING;
else
return ORD;
}
template <typename T> 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 <typename T, typename Cont>
auto output_element(std::ostream &os, const T &element, const Cont &) ->
typename std::enable_if<is_pair<typename Cont::value_type>::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 <typename T, typename Cont>
auto output_element(std::ostream &os, const T &element, const Cont &) ->
typename std::enable_if<!is_pair<typename Cont::value_type>::value,
bool>::type {
int etype = ischarOrString(element);
output(element, etype, os);
return false;
}
template <typename T, typename U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &pr) {
os << '(' << pr.first << ", " << pr.second << ')';
return os;
}
// template<typename T, typename Cont>
// auto output_element(std::ostream& os, const T& element,
// const Cont&, const std::true_type)
//-> decltype(std::declval<typename Cont::key_type>(), os)
//{
// os << element.first << " => " << element.second;
// return os;
// }
//
// template <typename T, typename Cont>
// auto output_element(std::ostream& os, const T& element,
// const Cont&, ...)
//-> decltype(os)
//{
// os << element;
// return os;
// }
// 针对没有输出函数的容器处理
template <typename T, typename = std::enable_if_t<!has_output_function_v<T>>>
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

View File

@@ -0,0 +1,40 @@
//
// Created by light on 20-1-7.
//
#include <array>
#include <iostream>
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<int, n> aa; // ok
std::array<int, factorial(10)> b; // cordump
int cc[rand()];
return 0;
}

View File

@@ -0,0 +1,25 @@
//
// Created by light on 20-1-10.
//
#include <iostream>
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.
}

View File

@@ -0,0 +1,27 @@
# please run `bazel run //learn_class/modern_cpp_30/container1:container`
# please run `bazel run //learn_class/modern_cpp_30/container1:vector_l`
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
cc_library(
name = "output_container",
hdrs = ["output_container.h"],
visibility = ["//visibility:public"],
)
cc_binary(
name = "container",
srcs = ["container.cpp"],
copts = ["-std=c++17"],
deps = [
":output_container",
],
)
cc_binary(
name = "vector_l",
srcs = ["vector_l.cpp"],
copts = ["-std=c++17"],
deps = [
":output_container",
],
)

View File

@@ -0,0 +1,17 @@
//
// Created by light on 19-12-16.
//
#include "output_container.h"
#include <iostream>
#include <map>
#include <vector>
using namespace std;
int main() {
map<int, int> mp{{1, 1}, {2, 4}, {3, 9}};
cout << mp << endl;
vector<vector<int>> vv{{1, 1}, {2, 4}, {3, 9}};
cout << vv << endl;
}

View File

@@ -0,0 +1,134 @@
/*
* Written by Wu Yongwei <wuyongwei AT gmail DOT com>.
*
* Using this file requires a C++17-compliant compiler.
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* For more information, please refer to <http://unlicense.org>
*
*/
#ifndef OUTPUT_CONTAINER_H
#define OUTPUT_CONTAINER_H
#include <ostream> // std::ostream
#include <type_traits> // std::false_type/true_type/decay_t/is_same_v
#include <utility> // std::declval/pair
// Type trait to detect std::pair
template <typename T> struct is_pair : std::false_type {};
template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type {};
template <typename T> inline constexpr bool is_pair_v = is_pair<T>::value;
// Type trait to detect whether an output function already exists
template <typename T> struct has_output_function {
template <class U>
static auto output(U *ptr)
-> decltype(std::declval<std::ostream &>() << *ptr, std::true_type());
template <class U> static std::false_type output(...);
static constexpr bool value = decltype(output<T>(nullptr))::value;
};
template <typename T>
inline constexpr bool has_output_function_v = has_output_function<T>::value;
/* NB: Visual Studio 2017 (or below) may have problems with
* has_output_function_v<T>: you should then use
* has_output_function<T>::value instead, or upgrade to
* Visual Studio 2019. */
// Output function for std::pair
template <typename T, typename U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &pr);
// Element output function for containers that define a key_type and
// have its value type as std::pair
template <typename T, typename Cont>
auto output_element(std::ostream &os, const T &element, const Cont &,
const std::true_type)
-> decltype(std::declval<typename Cont::key_type>(), os);
// Element output function for other containers
template <typename T, typename Cont>
auto output_element(std::ostream &os, const T &element, const Cont &, ...)
-> decltype(os);
// Main output function, enabled only if no output function already exists
template <typename T, typename = std::enable_if_t<!has_output_function_v<T>>>
auto operator<<(std::ostream &os, const T &container)
-> decltype(container.begin(), container.end(), os) {
using std::decay_t;
using std::is_same_v;
using element_type = decay_t<decltype(*container.begin())>;
constexpr bool is_char_v = is_same_v<element_type, char>;
if constexpr (!is_char_v) {
os << "{ ";
}
if (!container.empty()) {
auto end = container.end();
bool on_first_element = true;
for (auto it = container.begin(); it != end; ++it) {
if constexpr (is_char_v) {
if (*it == '\0') {
break;
}
}
if constexpr (!is_char_v) {
if (!on_first_element) {
os << ", ";
} else {
on_first_element = false;
}
}
output_element(os, *it, container, is_pair<element_type>());
}
}
if constexpr (!is_char_v) {
os << " }";
}
return os;
}
template <typename T, typename Cont>
auto output_element(std::ostream &os, const T &element, const Cont &,
const std::true_type)
-> decltype(std::declval<typename Cont::key_type>(), os) {
os << element.first << " => " << element.second;
return os;
}
template <typename T, typename Cont>
auto output_element(std::ostream &os, const T &element, const Cont &, ...)
-> decltype(os) {
os << element;
return os;
}
template <typename T, typename U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &pr) {
os << '(' << pr.first << ", " << pr.second << ')';
return os;
}
#endif // OUTPUT_CONTAINER_H

View File

@@ -0,0 +1,45 @@
//
// Created by light on 19-12-16.
//
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
class Obj1 {
public:
Obj1() { cout << "Obj1()\n"; }
Obj1(const Obj1 &) { cout << "Obj1(const Obj1&)\n"; }
Obj1(Obj1 &&) { cout << "Obj1(Obj1&&)\n"; }
};
class Obj2 {
public:
Obj2() { cout << "Obj2()\n"; }
Obj2(const Obj2 &) { cout << "Obj2(const Obj2&)\n"; }
Obj2(Obj2 &&) noexcept { cout << "Obj2(Obj2&&)\n"; }
};
int main() {
vector<int> v;
int nums = 20;
for (int i = 0; i < nums; ++i) {
v.push_back(i + 1);
cout << "v_size: " << v.size() << "\t v_capacity: " << v.capacity() << endl;
}
// 头两个在已有空间上成功构造。第三个时发现空间不足,系统会请求更大的空间,大小由实现决定(比如两倍)。
// 有了足够的空间后就会在新空间的第三个的位置构造第三个obj1成功之后再把头两个拷贝或移动过来。
vector<Obj1> v1;
// v1.reserve(2);
v1.emplace_back();
v1.emplace_back();
v1.emplace_back();
v1.emplace_back();
vector<Obj2> v2;
v2.reserve(2);
v2.emplace_back();
v2.emplace_back();
v2.emplace_back();
}

View File

@@ -0,0 +1,48 @@
# please run `bazel run //learn_class/modern_cpp_30/container2:relacontainer`
# please run `bazel run //learn_class/modern_cpp_30/container2:priority_queue`
# please run `bazel run //learn_class/modern_cpp_30/container2:hash`
# please run `bazel run //learn_class/modern_cpp_30/container2:array`
# please run `bazel run //learn_class/modern_cpp_30/container2:unorder`
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "relacontainer",
srcs = ["relacontainer.cpp"],
copts = ["-std=c++17"],
deps = [
"//learn_class/modern_cpp_30/container1:output_container",
],
)
cc_binary(
name = "priority_queue",
srcs = ["priority_queue.cpp"],
copts = ["-std=c++17"],
deps = [
"//learn_class/modern_cpp_30/container1:output_container",
],
)
cc_binary(
name = "hash",
srcs = ["hash.cpp"],
copts = ["-std=c++17"],
deps = [
"//learn_class/modern_cpp_30/container1:output_container",
],
)
cc_binary(
name = "array",
srcs = ["array.cpp"],
copts = ["-std=c++17"],
deps = [
"//learn_class/modern_cpp_30/container1:output_container",
],
)
cc_binary(
name = "unorder",
srcs = ["unorder.cpp"],
copts = ["-std=c++17"],
deps = [
"//learn_class/modern_cpp_30/container1:output_container",
],
)

View File

@@ -0,0 +1,42 @@
//
// Created by light on 19-12-16.
//
#include "../container1/output_container.h"
#include <iostream>
#include <map> // std::map
using namespace std;
#define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0]))
void test(int a[8]) { cout << ARRAY_LEN(a) << endl; }
void test1(int arr[]) {
// 不能编译
// std::cout << std::size(arr)
// << std::endl;
}
typedef char mykey_t[8];
typedef std::array<char, 8> mykey_t1;
int main() {
int a[8];
test(a);
// C++17 直接提供了一个 size 方法,可以用于提供数组长度,
int arr[] = {1, 2, 3, 4, 5};
std::cout << "The array length is " << std::size(arr) << std::endl;
// 并且在数组退化成指针的情况下会直接失败
test1(arr);
std::map<mykey_t, int> mp;
mykey_t mykey{"hello"};
// mp[mykey] = 5;
// 轰,大段的编译错误
std::map<mykey_t1, int> mp1;
mykey_t1 mykey1{"hello"};
mp1[mykey1] = 5; // ok
cout << mp1 << endl;
}

View File

@@ -0,0 +1,37 @@
//
// Created by light on 19-12-16.
//
#include "../container1/output_container.h"
#include <algorithm> // std::sort
#include <functional> // std::less/greater/hash
#include <iostream> // std::cout/endl
#include <string> // std::string
#include <vector> // std::vector
using namespace std;
int main() {
// 初始数组
vector<int> v{13, 6, 4, 11, 29};
cout << v << endl;
// 从小到大排序
sort(v.begin(), v.end());
cout << v << endl;
// 从大到小排序
sort(v.begin(), v.end(), greater<int>());
cout << v << endl;
cout << hex;
auto hp = hash<int *>();
cout << "hash(nullptr) = " << hp(nullptr) << endl;
cout << "hash(v.data()) = " << hp(v.data()) << endl;
cout << "v.data() = " << static_cast<void *>(v.data()) << endl;
auto hs = hash<string>();
cout << "hash(\"hello\") = " << hs(string("hello")) << endl;
cout << "hash(\"hellp\") = " << hs(string("hellp")) << endl;
}

View File

@@ -0,0 +1,26 @@
//
// Created by light on 19-12-16.
//
#include "../container1/output_container.h"
#include <functional> // std::greater
#include <iostream> // std::cout/endl
#include <memory> // std::pair
#include <queue> // std::priority_queue
#include <vector> // std::vector
using namespace std;
int main() {
priority_queue<pair<int, int>, vector<pair<int, int>>,
greater<pair<int, int>>>
q;
q.push({1, 1});
q.push({2, 2});
q.push({0, 3});
q.push({9, 4});
while (!q.empty()) {
cout << q.top() << endl;
q.pop();
}
}

View File

@@ -0,0 +1,57 @@
//
// Created by light on 19-12-16.
//
#include "../container1/output_container.h"
#include <functional>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <tuple>
using namespace std;
int main() {
set<int> s{1, 1, 1, 2, 3, 4};
cout << s << endl;
multiset<int, greater<int>> ms{1, 1, 1, 2, 3, 4};
cout << ms << endl;
map<string, int> mp{{"one", 1}, {"two", 2}, {"three", 3}, {"four", 4}};
cout << mp << endl;
mp.insert({"four", 4});
cout << mp << endl;
cout << (mp.find("four") == mp.end()) << endl;
cout << (mp.find("five") == mp.end()) << endl;
mp["five"] = 5;
cout << mp << endl;
multimap<string, int> mmp{{"one", 1}, {"two", 2}, {"three", 3}, {"four", 4}};
cout << mmp << endl;
mmp.insert({"four", -4});
cout << mmp << endl;
cout << (mp.find("four")->second) << endl;
cout << (mp.lower_bound("four")->second) << endl;
cout << (mp.upper_bound("four")->second) << endl;
cout << ((--mp.upper_bound("four"))->second) << endl;
multimap<string, int>::iterator lower, upper;
std::tie(lower, upper) = mmp.equal_range("four");
cout << (lower != upper) << endl; // 检测区间非空
cout << lower->second << endl;
cout << (--upper)->second << endl;
}

View File

@@ -0,0 +1,31 @@
//
// Created by light on 19-12-16.
//
#include "../container1/output_container.h"
#include <complex> // std::complex
#include <iostream> // std::cout/endl
#include <unordered_map> // std::unordered_map
#include <unordered_set> // std::unordered_set
using namespace std;
namespace std {
template <typename T> struct hash<complex<T>> {
size_t operator()(const complex<T> &v) const noexcept {
hash<T> h;
return h(v.real()) + h(v.imag());
}
};
} // namespace std
int main() {
unordered_set<int> s{1, 1, 2, 3, 5, 8, 13, 21};
cout << s << endl;
unordered_map<complex<double>, double> umc{{{1.0, 1.0}, 1.4142},
{{3.0, 4.0}, 5.0}};
cout << umc << endl;
}

View File

@@ -0,0 +1,9 @@
# please run `bazel run //learn_class/modern_cpp_30/exception:exception`
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "exception",
srcs = ["exception.cpp"],
copts = ["-std=c++11"],
)

View File

@@ -0,0 +1,21 @@
# please run `bazel run //learn_class/modern_cpp_30/functionLambda:adder`
# please run `bazel run //learn_class/modern_cpp_30/functionLambda:function`
# please run `bazel run //learn_class/modern_cpp_30/functionLambda:autoLambda`
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "adder",
srcs = ["adder.cpp"],
copts = ["-std=c++17"],
)
cc_binary(
name = "function",
srcs = ["function.cpp"],
copts = ["-std=c++17"],
)
cc_binary(
name = "autoLambda",
srcs = ["autoLambda.cpp"],
copts = ["-std=c++17"],
)

View File

@@ -0,0 +1,32 @@
//
// Created by light on 20-1-11.
//
#include <iostream>
using namespace std;
struct adder {
adder(int n) : n_(n) {}
int operator()(int x) const { return x + n_; }
private:
int n_;
};
int main() {
auto add_2 = adder(2);
// x+2
cout << add_2(3) << endl;
auto t = bind1st(plus<int>(), 2);
cout << t(1) << endl;
// 上述的C++98
binder2nd<plus<int>> a2(plus<int>(), 2);
cout << a2(3) << endl;
cout << [](int x) { return x * x; }(3) << endl;
return 0;
// lambda表达式默认就是constexpr函数
}

View File

@@ -0,0 +1,58 @@
//
// Created by light on 20-1-11.
//
#include <chrono>
#include <iostream>
#include <sstream>
#include <thread>
using namespace std;
int get_count() {
static int count = 0;
return ++count;
}
class task {
public:
task(int data) : data_(data) {}
/**
* this 标明按引用捕获外围对象(针对 lambda
* 表达式定义出现在一个非静态类成员内的情况); 注意默认捕获符 = 和 &
* 号可以自动捕获 this并且在 C++20 之前,在 = 后写 this 会导致出错)
* 本例子两次都按照第二次输出(this_thread::sleep_for(100ms);
* this 标明按引用捕获外围对象
*
*
* *this 标明按值捕获外围对象(针对 lambda
* 表达式定义出现在一个非静态类成员内的情况C++17 新增语法) 本例子正常输出
*/
auto lazy_launch() {
return [*this, count = get_count()]() mutable {
ostringstream oss;
oss << "Done work " << data_ << " (No. " << count << ") in thread "
<< this_thread::get_id() << '\n';
msg_ = oss.str();
calculate();
};
}
void calculate() {
this_thread::sleep_for(100ms);
cout << msg_;
}
private:
int data_;
string msg_;
};
int main() {
auto t = task{37};
thread t1{t.lazy_launch()};
thread t2{t.lazy_launch()};
t1.join();
t2.join();
}

View File

@@ -0,0 +1,19 @@
//
// Created by light on 20-1-11.
//
#include <functional>
#include <iostream>
#include <map>
using namespace std;
int main() {
map<string, function<int(int, int)>> op_dict{
{"+", [](int x, int y) { return x + y; }},
{"-", [](int x, int y) { return x - y; }},
{"*", [](int x, int y) { return x * y; }},
{"/", [](int x, int y) { return x / y; }},
};
}

Some files were not shown because too many files have changed in this diff Show More