// Code from ./9/main.cpp
#include <iostream>
#include <span>
#include <vector>
template <typename T> void print(std::span<T> span) noexcept {
for (const auto &i : span) {
std::cout << i << " ";
}
std::cout << std::endl;
std::cout << span.size() << std::endl;
}
int main() {
std::vector v{1, 2, 3, 4, 5};
int n[]{1, 2, 3, 4, 5};
std::vector<std::string> s{"1", "2", "3"};
print<int>(v);
print<int>(n);
print<std::string>(s);
// NOTE::span只是view开销更小,只保存数据的开始位置和长度
// NOTE::幽默clangd疯狂报错
return 0;
}
// Code from ./8/main.cpp
#include <iostream>
int main() {
double v1 = 1.0, v2 = 2.0;
auto ret = v1 <=> v2;
if (ret < 0) {
std::cout << "v1 < v2" << std::endl;
} else if (ret > 0) {
std::cout << "v1 > v2" << std::endl;
} else {
std::cout << "v1 = v2" << std::endl;
}
// NOTE::幽默clangd居然报错了,g++编译通过
return 0;
}
// Code from ./1/main.cpp
#include <iostream>
#include <memory>
void f(int, int, int = 10);
void f(int, int = 6, int);
void f(int = 5, int, int);
// void f(int = 6, int = 7, int = 9); NOTE::重定义会报错
// void f(int = 7,int ,int );NOTE::报错原因同上
void f(int a, int b, int c) {
std::cout << "a=" << a << " b=" << b << " c=" << c << std::endl;
}
void fun(int, int, int = 10); // NOTE::如果没有这一行会报错
void fun(int, int = 6, int);
void fun(int = 5, int, int);
void fun(int a, int b, int c) {
std::cout << "a=" << a << " b=" << b << " c=" << c << std::endl;
}
class C {
// void f(int i = 3, int j, int k =
// 6);//NOTE::报错,只要不是最后一个参数外的其他参数有默认参数,那么所有参数都要加默认参数
void g(int i, int b,
int j = 99); // NOTE::没有报错,因为只有最后一个参数有默认构造函数
C(int arg);
};
class X {
// void f(int a, int b, int c = 4, int
// d);//NOTE::报错,第三个参数有默认参数,而其他参数没有
};
// NOTE::非模板类的成员函数类外的定义允许出现默认实参,并与类体内的声明所提供的默认实参组合
// void C::f(int i=3);NOTE::重定义报错
// void C::f(int i, int j = 5, int k) {}
// void C::g(int i = 88, int j);NOTE::导致在作用域外面声明一个函数,报错
// C::C(int arg = 1) {};//NOTE::报错
struct Base {
virtual void f(int a = 7) { std::cout << "Base" << a << std::endl; }
};
struct Derived : Base {
// NOTE::虚函数的覆盖不会从基类定义获得默认实参,而进行虚函数调用时,默认实参根据对象的静态类型确定
void f(int a) override { std::cout << "Derived" << a << std::endl; }
// NOTE::输出Derived 7
};
int main() {
f();
std::unique_ptr<Base> ptr{new Derived}; // NOTE::这里ptr的静态类型是Base
ptr->f();
return 0;
}
// Code from ./2/main.cpp
#include <functional>
#include <iostream>
struct X {
void f() { std::cout << "6" << std::endl; }
int num = 0;
};
void f2(void (X::*p)(), X &x) { (x.*p)(); }
int main() {
void (X::*p)() = &X::f; // NOTE::成员函数指针
X x;
(x.*p)(); // NOTE::调用成员函数指针,输出6
f2(p, x);
f2(&X::f, x);
X c;
int &i = std::invoke(&X::num, &c);
i = 114545;
std::cout << c.num << std::endl;
return 0;
}
// Code from ./11/main.cpp
#include <iostream>
struct X {
X(const X &) = delete;
X(int) {}
X(double) = delete;
};
void f(int) {}
void f(double) = delete;
void f2(std::integral auto) {} // NOTE::这样也可以防止隐式转换
// NOTE::幽默clangd又报错了
int main() {
f(1);
// NOTE::f(1.2);报错
X x(1);
// NOTE::X *x = new X(1);报错
return 0;
}
// Code from ./6/main.cpp
#include <iostream>
class X {};
template <typename T> static void f1(T &&x) {
std::cout << &x << std::endl;
f2(std::forward<X>(x));
}
template <typename T> static void f2(T &&x) {
std::cout << &x << std::endl;
f3(std::forward<X>(x));
}
template <typename T> static void f3(T &&x) {
std::cout << &x << std::endl;
f4(std::forward<X>(x));
}
template <typename T> static void f4(T &&x) {
std::cout << &x << std::endl;
f5(std::forward<X>(x));
}
template <typename T> static void f5(T &&x) { std::cout << &x << std::endl; }
int main() {
X x;
f1(std::move(x));
// NOTE::两个知识点,c++17强制规定复制消除
// NOTE::forward将函数接收到的参数以原本的值类别传播,而不是右值引用退化为左值
return 0;
}
// Code from ./10/main.cpp
#include <iostream>
#include <string>
#include <type_traits>
template <typename T> struct A {
A(T){};
T t;
};
template <typename T> A(T) -> A<double>; // NOTE::显式的推导引导
A(const char *) -> A<std::string>; // NOTE::如果推导出了const
// char*,则推导为string
template <typename T, size_t size> struct array {
T arr[size];
};
template <class Tu, class... Tp>
array(Tu, Tp...) -> array<std::enable_if_t<(std::is_same_v<Tu, Tp> && ...), Tu>,
sizeof...(Tp) + 1>;
int main() {
// NOTE::c++17开始可以类模板实参推导
// NOTE::就像模板函数一样
auto t = new A{1};
// NOTE::分配的类型为A<int>,但因为推导引导,推导为了double
array arr{1, 2, 3, 4};
return 0;
}
// Code from ./5/main.cpp
#include <iostream>
int f() { return 6; }
int main() {
// NOTE::函数返回的是纯右值
int &&p = f();
const int &pp = f();
using T = decltype((42)); // NOTE::int纯右值
using T2 = decltype((5.2)); // NOTE::double纯右值
int v{};
using T3 = decltype((v)); // NOTE::int&左值表达式
using T4 = decltype(static_cast<int &&>(v)); // NOTE:: int&& 亡值表达式
return 0;
}
// Code from ./4/main.cpp
#include <cstring>
#include <iostream>
struct test {
int a;
double b;
char c[0];
// NOTE::长度为0的数组,即柔性数组
};
int main() {
auto t = static_cast<test *>(malloc(sizeof(test) + 27 * sizeof(char)));
memset(t->c, 0, 27);
for (int i = 0; i < 26; ++i) {
t->c[i] = 'A' + i;
}
std::cout << t->c << std::endl;
free(t);
return 0;
}
// Code from ./3/main.cpp
#include <iostream>
int main() {
static int a = 42;
auto f = [=]() -> void { ++a; };
f();
std::cout << "a=" << a << std::endl;
std::cout << "sizeof f:" << sizeof f << std::endl;
// NOTE::输出a=43, sizeof f:1
const int N = 1145;
auto p = [=] { int arr[N]; };
std::cout << "sizeof p" << sizeof p << std::endl;
// NOTE::输出sizeof p 1,说明根本没捕获N
auto pp = [=] { int p = N; };
std::cout << "sizeof pp" << sizeof pp << std::endl;
// NOTE::gcc输出sizeof p 1,说明根本没捕获N,但msvc会输出4
return 0;
}
// Code from ./7/main.cpp
#include <iostream>
struct S {
void f() & { std::cout << "left value" << std::endl; }
void f() && { std::cout << "r value" << std::endl; }
};
int main() {
S s;
s.f(); // NOTE::left value
std::move(s).f(); // NOTE:: right value
S().f(); // NOTE:: right value
return 0;
}