support bazel complie this project and format code.
This commit is contained in:
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.
|
||||
}
|
Reference in New Issue
Block a user