Skip to content

Latest commit

 

History

History
226 lines (197 loc) · 5 KB

c++20-is-design-complete.org

File metadata and controls

226 lines (197 loc) · 5 KB

c++ 20 is design complete

As of the KONA meeting C++ 20 is Design Complete

  • All Major Features are in or out
  • No new features not already seen
  • It is big

What isn’t in

  • Networking
  • Executors
  • Static Exception (Herbceptions)
  • Reflection

Core Features

  • Contracts
  • Coroutines
  • Concepts
  • Comparison, three-way
  • Modules
  • String Literals as Template Parameters
  • consteval
  • char8_t
  • char{N}_t is UTF-{N}

Library Features

  • Ranges

Contracts

int z;
bool is_prime(int k);
void f(int x)
[[expects: x > 0]]
[[expects audit: is_prime(x)]]
[[ensures: z > 10]]
{
/* ... */
}

Coroutines

  • “Stackless” : on the callers stack, not thread like
  • Heap allocated activation record
  • Transfer of control deterministic from a language point of view

Example

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());
}

Example Task

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;
}

Concepts

  • 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

Example

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 // ...
{//...
};

Comparison, three-way

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

Example

struct bar
{
    int i;
    std::strong_ordering operator<=>(bar const& rhs) { return i <=> rhs.i; }
};

Modules

  • 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

String Literals as Template Parameters

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;
    }
}

consteval

Constexpr all the things!

consteval int sqr(int n) {
  return n*n;
}
constexpr int r = sqr(100);

char8_t

A new character type which is always encoded as UTF-8

char{N}_t is UTF-{N}

char16_t is UTF-16

char32 is UTF-32

Everyone did this, but now it’s actually Standard

Ranges

The Haskell List Monad ported to C++ (don’t tell)