support bazel complie this project and format code.
This commit is contained in:
Binary file not shown.
@@ -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)
|
@@ -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")
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
}
|
Binary file not shown.
@@ -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;
|
||||
}
|
@@ -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;
|
||||
}
|
Binary file not shown.
@@ -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;
|
||||
|
||||
}
|
@@ -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';
|
||||
|
||||
}
|
@@ -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
|
@@ -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;
|
||||
}
|
@@ -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.
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
}
|
@@ -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
|
@@ -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();
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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函数
|
||||
}
|
@@ -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();
|
||||
}
|
||||
|
@@ -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;
|
||||
}},
|
||||
};
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
};
|
@@ -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;
|
||||
}
|
@@ -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 类不可派生
|
||||
};
|
@@ -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;
|
||||
}
|
@@ -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());
|
||||
}
|
@@ -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();
|
||||
}
|
@@ -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();
|
||||
}
|
@@ -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();
|
||||
}
|
@@ -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();
|
||||
}
|
@@ -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 不可拷贝
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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>
|
||||
}
|
@@ -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 调用带模板的移动构造
|
||||
}
|
21
learn_class/modern_cpp_30/RAII/BUILD
Normal file
21
learn_class/modern_cpp_30/RAII/BUILD
Normal 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"],
|
||||
)
|
82
learn_class/modern_cpp_30/RAII/RAII.cpp
Normal file
82
learn_class/modern_cpp_30/RAII/RAII.cpp
Normal 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;
|
||||
}
|
35
learn_class/modern_cpp_30/RAII/heap.cpp
Normal file
35
learn_class/modern_cpp_30/RAII/heap.cpp
Normal 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;
|
||||
}
|
23
learn_class/modern_cpp_30/RAII/stack.cpp
Normal file
23
learn_class/modern_cpp_30/RAII/stack.cpp
Normal 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);
|
||||
}
|
||||
}
|
33
learn_class/modern_cpp_30/SFINAE/SFINAE.cpp
Normal file
33
learn_class/modern_cpp_30/SFINAE/SFINAE.cpp
Normal 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;
|
||||
}
|
27
learn_class/modern_cpp_30/compilercompute/BUILD
Normal file
27
learn_class/modern_cpp_30/compilercompute/BUILD
Normal 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"],
|
||||
)
|
43
learn_class/modern_cpp_30/compilercompute/IF.cpp
Normal file
43
learn_class/modern_cpp_30/compilercompute/IF.cpp
Normal 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;
|
||||
}
|
57
learn_class/modern_cpp_30/compilercompute/WhileLoop.cpp
Normal file
57
learn_class/modern_cpp_30/compilercompute/WhileLoop.cpp
Normal 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;
|
||||
}
|
20
learn_class/modern_cpp_30/compilercompute/factorial.cpp
Normal file
20
learn_class/modern_cpp_30/compilercompute/factorial.cpp
Normal 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;
|
||||
}
|
34
learn_class/modern_cpp_30/compilercompute/fmap.cpp
Normal file
34
learn_class/modern_cpp_30/compilercompute/fmap.cpp
Normal 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;
|
||||
}
|
9
learn_class/modern_cpp_30/compilerpoly/BUILD
Normal file
9
learn_class/modern_cpp_30/compilerpoly/BUILD
Normal 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"],
|
||||
)
|
30
learn_class/modern_cpp_30/constexpr/BUILD
Normal file
30
learn_class/modern_cpp_30/constexpr/BUILD
Normal 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"],
|
||||
)
|
32
learn_class/modern_cpp_30/constexpr/container.cpp
Normal file
32
learn_class/modern_cpp_30/constexpr/container.cpp
Normal 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;
|
||||
}
|
73
learn_class/modern_cpp_30/constexpr/newconstexpr.cpp
Normal file
73
learn_class/modern_cpp_30/constexpr/newconstexpr.cpp
Normal 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';
|
||||
}
|
134
learn_class/modern_cpp_30/constexpr/output_container.h
Normal file
134
learn_class/modern_cpp_30/constexpr/output_container.h
Normal 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
|
40
learn_class/modern_cpp_30/constexpr/sqrt.cpp
Normal file
40
learn_class/modern_cpp_30/constexpr/sqrt.cpp
Normal 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;
|
||||
}
|
25
learn_class/modern_cpp_30/constexpr/test3.cpp
Normal file
25
learn_class/modern_cpp_30/constexpr/test3.cpp
Normal 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.
|
||||
}
|
27
learn_class/modern_cpp_30/container1/BUILD
Normal file
27
learn_class/modern_cpp_30/container1/BUILD
Normal 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",
|
||||
],
|
||||
)
|
17
learn_class/modern_cpp_30/container1/container.cpp
Normal file
17
learn_class/modern_cpp_30/container1/container.cpp
Normal 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;
|
||||
}
|
134
learn_class/modern_cpp_30/container1/output_container.h
Normal file
134
learn_class/modern_cpp_30/container1/output_container.h
Normal 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
|
45
learn_class/modern_cpp_30/container1/vector_l.cpp
Normal file
45
learn_class/modern_cpp_30/container1/vector_l.cpp
Normal 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();
|
||||
}
|
48
learn_class/modern_cpp_30/container2/BUILD
Normal file
48
learn_class/modern_cpp_30/container2/BUILD
Normal 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",
|
||||
],
|
||||
)
|
42
learn_class/modern_cpp_30/container2/array.cpp
Normal file
42
learn_class/modern_cpp_30/container2/array.cpp
Normal 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;
|
||||
}
|
37
learn_class/modern_cpp_30/container2/hash.cpp
Normal file
37
learn_class/modern_cpp_30/container2/hash.cpp
Normal 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;
|
||||
}
|
26
learn_class/modern_cpp_30/container2/priority_queue.cpp
Normal file
26
learn_class/modern_cpp_30/container2/priority_queue.cpp
Normal 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();
|
||||
}
|
||||
}
|
57
learn_class/modern_cpp_30/container2/relacontainer.cpp
Normal file
57
learn_class/modern_cpp_30/container2/relacontainer.cpp
Normal 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;
|
||||
}
|
31
learn_class/modern_cpp_30/container2/unorder.cpp
Normal file
31
learn_class/modern_cpp_30/container2/unorder.cpp
Normal 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;
|
||||
}
|
9
learn_class/modern_cpp_30/exception/BUILD
Normal file
9
learn_class/modern_cpp_30/exception/BUILD
Normal 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"],
|
||||
)
|
21
learn_class/modern_cpp_30/functionLambda/BUILD
Normal file
21
learn_class/modern_cpp_30/functionLambda/BUILD
Normal 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"],
|
||||
)
|
32
learn_class/modern_cpp_30/functionLambda/adder.cpp
Normal file
32
learn_class/modern_cpp_30/functionLambda/adder.cpp
Normal 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函数
|
||||
}
|
58
learn_class/modern_cpp_30/functionLambda/autoLambda.cpp
Normal file
58
learn_class/modern_cpp_30/functionLambda/autoLambda.cpp
Normal 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();
|
||||
}
|
19
learn_class/modern_cpp_30/functionLambda/function.cpp
Normal file
19
learn_class/modern_cpp_30/functionLambda/function.cpp
Normal 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
Reference in New Issue
Block a user