- All Major Features are in or out
- No new features not already seen
- It is big
- Networking
- Executors
- Static Exception (Herbceptions)
- Reflection
- Contracts
- Coroutines
- Concepts
- Comparison, three-way
- Modules
- String Literals as Template Parameters
consteval
- char8_t
- char{N}_t is UTF-{N}
- Ranges
int z;
bool is_prime(int k);
void f(int x)
[[expects: x > 0]]
[[expects audit: is_prime(x)]]
[[ensures: z > 10]]
{
/* ... */
}
- “Stackless” : on the callers stack, not thread like
- Heap allocated activation record
- Transfer of control deterministic from a language point of view
namespace
{
cppcoro::generator<int> range(int start, int end)
{
for (; start < end; ++start)
{
co_yield start;
}
}
}
TEST_CASE("fmap operator")
{
cppcoro::generator<int> gen = range(0, 5)
| cppcoro::fmap([](int x) { return x * 3; });
auto it = gen.begin();
CHECK(*it == 0);
CHECK(*++it == 3);
CHECK(*++it == 6);
CHECK(*++it == 9);
CHECK(*++it == 12);
CHECK(++it == gen.end());
}
cppcoro::task<int> count_lines(std::string path)
{
auto file = co_await cppcoro::read_only_file::open(path);
int lineCount = 0;
char buffer[1024];
size_t bytesRead;
std::uint64_t offset = 0;
do
{
bytesRead = co_await file.read(offset, buffer, sizeof(buffer));
lineCount += std::count(buffer, buffer + bytesRead, '\n');
offset += bytesRead;
} while (bytesRead > 0);
co_return lineCount;
}
cppcoro::task<> usage_example()
{
cppcoro::task<int> countTask = count_lines("foo.txt");
// ...
// Coroutine is only started when we later co_await the task.
int lineCount = co_await countTask;
std::cout << "line count = " << lineCount << std::endl;
}
- boolean requirements used to constrain types
- Syntax checks, not semantic checks
- No checking of template instantiations
- means that you can os << t even if you didn’t require an ostreamable t
template <class T>
concept bool Nullable =
std::is_object_v<T> &&
requires(T& t, const T& ct) {
bool(ct);
*t;
*ct;
};
template <Nullable Maybe>
requires ranges::CopyConstructible<Maybe>
class maybe_view // ...
{//...
};
The SpaceShip Operator <=>
(a <=> b) < 0 //true if a < b
(a <=> b) > 0 //true if a > b
(a <=> b) == 0 //true if a is equal/equivalent to b
The language can use this if you define it to derive all the comparison operators
struct bar
{
int i;
std::strong_ordering operator<=>(bar const& rhs) { return i <=> rhs.i; }
};
- Nothing to do with packaging.
- Probably breaks packaging.
- All about controlled access to names and visibility of components
- Two kinds
- Header Units
- macros come out
- everything else does
- Modules
- macros do not
- control of what is visible
- Header Units
Compile Time Regular Expressions!
std::optional<std::string_view>
extract_number(std::string_view s) noexcept
{
if (auto m = ctre::match<"^[a-z]++([0-9]++)$">(s))
{
return m.get<1>().to_view();
} else {
return std::nullopt;
}
}
Constexpr all the things!
consteval int sqr(int n) {
return n*n;
}
constexpr int r = sqr(100);
A new character type which is always encoded as UTF-8
char16_t is UTF-16
char32 is UTF-32
Everyone did this, but now it’s actually Standard
The Haskell List Monad ported to C++ (don’t tell)