-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
705de18
commit 32d4ca0
Showing
17 changed files
with
834 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# C++17 vs C++20 | ||
|
||
> https://eel.is/c++draft/ | ||
## Core | ||
[initializer](initializer.md) | [lambda](lambda.md) | [concepts](concepts.md) | [constexpr](constexpr.md) | [consteval](consteval.md) | [coroutines](coroutines.md) | [modules](modules.md) | [misc](misc.md) | ||
|
||
## STL | ||
[format](format.md) | [ranges](ranges.md) | ||
|
||
## Meta | ||
[nttp](nttp.md) | [fixed_string](fixed_string.md) | [reflection](reflection.md) | [tmp](tmp.md) | ||
|
||
## Others | ||
[testing](testing.md) | [performance](performance.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Concepts | ||
|
||
> syntax | ||
C++17 | ||
```cpp | ||
template<class T> auto parse(T); | ||
``` | ||
C++20: | ||
```cpp | ||
auto parse(auto); | ||
``` | ||
|
||
> Note: auto = weakest concept // template<class T> Auto = true; // always satisfied | ||
> constraints | ||
C++17 - SFINAE | ||
```cpp | ||
template<class T, std::enable_if_t<Constrained, bool> = true> | ||
auto parse(T); | ||
``` | ||
C++20 | ||
```cpp | ||
template<class T> concept = Constrained; | ||
template<Constrained T> auto parse(T); | ||
``` | ||
or | ||
```cpp | ||
template<class T> requires Constrained<T> auto parse(T); | ||
``` | ||
Note: destructors can be constrained and there is not need for type | ||
```cpp | ||
~parser() requires std::abstract<T> = default; | ||
``` | ||
|
||
Note: tere syntax | ||
```cpp | ||
auto parse(Constrained auto); | ||
``` | ||
> Design by introspection (Andrei Alexandrescu) | ||
C++17 | ||
```cpp | ||
template<class T> using has_foo = decltype(std::declval<T&>().foo); | ||
if constexpr(std::is_detected<has_foo, T>) { | ||
// ... | ||
} | ||
``` | ||
|
||
C++20 | ||
```cpp | ||
if constexpr (requires(T t) { t.foo; }) { | ||
// ... | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# consteval - like constexpr but only at compile-time | ||
|
||
```cpp | ||
[[nodiscard]] consteval parse(auto t) { | ||
// ... | ||
return t; | ||
} | ||
``` | ||
```cpp | ||
int main(int argc, char**) { | ||
constexpr auto = parse(42); // okay | ||
auto = parse(argc); // error, not a constant expression | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# constexpr | ||
|
||
- virtual | ||
- std::unique_ptr | ||
- std::string | ||
- std::vector | ||
- ... | ||
|
||
> Example - constexpr std::function | ||
```cpp | ||
template <class> | ||
class function; | ||
|
||
template <class R, class... TArgs> | ||
class function<R(TArgs...)> { | ||
struct interface { | ||
constexpr virtual auto operator()(TArgs...) -> R = 0; | ||
constexpr virtual ~interface() = default; | ||
}; | ||
|
||
template <class Fn> | ||
struct implementation final : interface { | ||
constexpr explicit(true) implementation(Fn fn) : fn{fn} {} | ||
constexpr auto operator()(TArgs... args) -> R { return fn(args...); } | ||
|
||
private: | ||
Fn fn{}; | ||
}; | ||
|
||
public: | ||
template <class Fn> | ||
constexpr function(Fn fn) : fn{std::make_unique<implementation<Fn>>(fn)} {} | ||
|
||
constexpr auto operator()(TArgs... args) const -> R { | ||
return (*fn)(args...); | ||
} | ||
|
||
private: | ||
std::unique_ptr<interface> fn{}; | ||
}; | ||
|
||
template <class> | ||
struct function_traits {}; | ||
|
||
template <class R, class B, class... TArgs> | ||
struct function_traits<R (B::*)(TArgs...) const> { | ||
using type = R(TArgs...); | ||
}; | ||
|
||
template <class F> | ||
function(F) -> function<typename function_traits<decltype(&F::operator())>::type>; | ||
``` | ||
```cpp | ||
consteval auto test_empty() { | ||
function f = [] { return 42; }; | ||
return f(); | ||
} | ||
consteval auto test_arg() { | ||
function f = [](int i) { return i; }; | ||
return f(42); | ||
} | ||
consteval auto test_capture() { | ||
int i = 42; | ||
function f = [&] { return i; }; | ||
return f(); | ||
} | ||
static_assert(42 == test_empty()); | ||
static_assert(42 == test_arg()); | ||
static_assert(42 == test_capture()); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# State Machine | ||
|
||
C++17 | ||
```cpp | ||
constexpr auto establish = [] { std::puts("establish"); }; | ||
constexpr auto close = [] { std::puts("close"); }; | ||
constexpr auto is_valid = [] { return true; }; | ||
constexpr auto reset = [] { std::puts("reset"); }; | ||
|
||
sml::sm connection = [] { | ||
using namespace sml; | ||
return transition_table{ | ||
* "Disconnected"_s + event<connect> / establish = "Connecting"_s, | ||
"Connecting"_s + event<established> = "Connected"_s, | ||
"Connected"_s + event<ping> [ is_valid ] / reset_timeout, | ||
"Connected"_s + event<timeout> / establish = "Connecting"_s, | ||
"Connected"_s + event<disconnect> / close = "Disconnected"_s | ||
}; | ||
}; | ||
``` | ||
``` | ||
int main() { | ||
connection.process_event(connect{}); | ||
connection.process_event(established{}); | ||
connection.process_event(ping{}); | ||
connection.process_event(disconnect{}); | ||
} | ||
``` | ||
C++20 | ||
```cpp | ||
constexpr auto establish = [] { std::puts("establish"); }; | ||
constexpr auto close = [] { std::puts("close"); }; | ||
constexpr auto is_valid = [] { return true; }; | ||
constexpr auto reset = [] { std::puts("reset"); }; | ||
class Connection { | ||
state connection() { | ||
for (;;) { | ||
disconnected: | ||
if (auto [event, data] = co_await sm; event == connect{}) { | ||
establish(); | ||
connecting: | ||
if (auto [event, data] = co_await sm; event == established{}) { | ||
connected: | ||
switch (auto [event, data] = co_await sm; event) { | ||
case ping{}: | ||
if (is_valid(data)) reset(); | ||
goto connected; | ||
case timeout{}: | ||
establish(); | ||
goto connecting; | ||
case disconnect{}: | ||
close(); | ||
goto disconnected; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
public: | ||
void process_event(const auto& event) { sm.process_event(event); } | ||
private: | ||
state_machine<int> sm{}; | ||
state initial{connection()}; | ||
}; | ||
int main() { | ||
Connection connection{}; | ||
connection.process_event(connect{}); | ||
connection.process_event(established{}); | ||
connection.process_event(ping{}); | ||
connection.process_event(disconnect{}); | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
# fixed_string (compile-time string) | ||
|
||
```cpp | ||
template<char....> struct ct_string{}; | ||
``` | ||
|
||
C++17 via gnu-extension | ||
|
||
```cpp | ||
template<class T, T... Cs> | ||
constexpr auto operator""_cs() { return ct_string<Cs...>{}; } | ||
|
||
template<class> struct foo {}; | ||
foo<decltype("bar"_cs)>; | ||
``` | ||
C++20 via fixed_string | ||
```cpp | ||
template <std::size_t N> | ||
struct fixed_string final { | ||
constexpr explicit(true) fixed_string(const auto... cs) : data{cs...} {} | ||
constexpr explicit(false) fixed_string(const char (&str)[N + 1]) { | ||
std::copy_n(str, N + 1, std::data(data)); | ||
} | ||
[[nodiscard]] constexpr auto operator<=>(const fixed_string&) const = default; | ||
[[nodiscard]] constexpr explicit(false) operator std::string_view() const { | ||
return {std::data(data), N}; | ||
} | ||
[[nodiscard]] constexpr auto size() const -> std::size_t { return N; } | ||
std::array<char, N + 1> data{}; | ||
}; | ||
``` | ||
|
||
```cpp | ||
template<fixed_string> struct foo {}; | ||
foo<"bar"> f{}; | ||
``` | ||
> Note: fixed_string doesn't have external linkage | ||
```cpp | ||
template <stdext::fixed_string Str> | ||
static auto to_string = []<auto... Ns>(std::index_sequence<Ns...>) { | ||
return ct_string<Str.data[Ns]...>{}; | ||
}(std::make_index_sequence<Str.size()>{}); | ||
``` | ||
|
||
```cpp | ||
static_assert(ct_string<'f', 'o', 'o'> == to_string<"foo">) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# std.format | ||
|
||
C++17 | ||
fmt.format | ||
|
||
C++20 | ||
```cpp | ||
static_assert("42"sv == fmt::format("{}", 42)); | ||
static_assert("42.."sv == fmt::format("{:.<4}", 42)); | ||
static_assert("..42"sv == fmt::format("{:.>4}", 42)); | ||
static_assert("42 0x2a"sv == fmt::format("{0} {0:#x}", 42)); // use 0 parameter | ||
static_assert(" QL "sv == fmt::format("{:^6}", "QL")); | ||
static_assert(" QL "sv == fmt::format("{:>4} ", "QL")); | ||
static_assert("QL "sv == fmt::format("{:<{}}", "QL", 10)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Designated initliazers | ||
|
||
```cpp | ||
struct msg { | ||
int type; | ||
int value; | ||
} | ||
``` | ||
C++17 | ||
```cpp | ||
auto m = msg{42, 42}; // error prone | ||
``` | ||
|
||
> for safety strong types would be preferred | ||
|
||
|
||
C++20 | ||
```cpp | ||
auto m = msg{.type = 42, .value = 42}; | ||
``` | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Lambdas | ||
|
||
```cpp | ||
template<auto N> constexpr auto unroll = [](auto expr) { | ||
[expr]<auto ...Is>(std::index_sequence<Is...>) { | ||
((expr(), void(Is)), ...); | ||
}(std::make_index_sequence<N>{}); | ||
}; | ||
``` | ||
|
||
```cpp | ||
int main() { | ||
unroll<2>([]{ std::puts("!"); }); | ||
} | ||
``` | ||
|
||
```asm | ||
.LC0: .string "!" | ||
main: | ||
sub rsp, 8 | ||
mov edi, OFFSET FLAT:.LC0 | ||
call puts | ||
mov edi, OFFSET FLAT:.LC0 | ||
call puts | ||
xor eax, eax | ||
add rsp, 8 | ||
ret | ||
``` | ||
|
||
Note: How to call templated lambda? | ||
|
||
```cpp | ||
auto l = []<auto...> {}; | ||
l.template operator()<42>() | ||
``` | ||
|
||
> Lambda types | ||
```cpp | ||
static_assert(typeid([]{}) != typeid([]{})); | ||
``` | ||
```cpp | ||
static_assert(+[]{} != +[]{}); | ||
``` | ||
|
||
```cpp | ||
auto expr = decltype([]{}){}; | ||
``` |
Oops, something went wrong.