PrevUpHomeNext

Home:: tiv.cc

CPP23 IQL Jan 2023 Q1


CPP23 Incomplete Quick Look Jan 2023 Q1

CPP23: c++23 Incomplete Quick Look, January 2023, Q1.

January is the first month of the new year, what will c++23 look like?





All code are passed by g++(gcc) compiler.

cpp23: c++23 - January 2023

Top



Multidimensional Subscript operator[]

Example

#include <utxcpp/core.hpp>
#include <vector>
#include <numeric>

class fizz_box
{
private:
	int x, y, z, w;
	std::vector<int> vector;
public:
	fizz_box(int x, int y, int z, int w):
		x{x}, y{y}, z{z}, w{w},
		vector(x*y*z*w)
	{
		std::iota(vector.begin(), vector.end(), 1);
	}
	void print_all()
	{
		utx::print("------------------------------------------------------------------------");
		for (int i=0; i<x; i++)
		{
			for (int j=0; j<y; j++)
			{
				for (int k=0; k<z; k++)
				{
					for (int u=0; u<w; u++)
					{
						int index = i*y*z*w + j*z*w + k*w + u;
						utx::printnl(vector[index], "");
					}
					utx::print();
				}
				utx::print();
			}
			utx::print("------------------------------------------------------------------------");
		}
	}
	
	// Multidimensional Subscript operator[]
	int operator[](int i, int j, int k, int u)
	{
		int index = i*y*z*w + j*z*w + k*w + u;
		return vector[index];
	}
};

int main()
{
	fizz_box box{2,3,2,3};
	box.print_all();
	int i=1, j=2, k=1, u=1;
	utx::print(i,j,k,u, "=>", box[i,j,k,u]);
}

Output:

------------------------------------------------------------------------
1 2 3
4 5 6

7 8 9
10 11 12

13 14 15
16 17 18

------------------------------------------------------------------------
19 20 21
22 23 24

25 26 27
28 29 30

31 32 33
34 35 36

------------------------------------------------------------------------
1 2 1 1 => 35

Top



static operator() and operator[]

Example

#include <iostream>

class fizz_box
{
public:
	static int operator()(int x)
	{
		return x*x;
	}
	static int operator[](int x)
	{
		return x*x*x;
	}
};

int main()
{
	std::cout << fizz_box::operator()(3) << ' '
		<< fizz_box::operator[](3) << std::endl;
}

Top



if consteval

Example

#include <utxcpp/core.hpp>
#include <ranges>

constexpr bool func()
{
	if consteval
	{
		return true;
	}
	else
	{
		return false;
	}
}

constexpr auto fn = []
{
	if ! consteval
	{
		return false;
	}
	else
	{
		return true;
	}
};

int main()
try
{
	static_assert(func() == true);
	utx::rt_assert(func() == false);
	
	static_assert(fn() == true);
	utx::rt_assert(fn() == false);
}
catch (std::exception & e)
{
	utx::printe(e.what());
}

Top



Literal Suffix for std::size_t

#include <utxcpp/core.hpp>

int main()
{
	// Literal suffix for std::size_t
	auto x = 123uz;
	
	utx::same_assert<decltype(x), std::size_t, true>{};
}

Top



New Header: <expected> std::expected and std::unexpected

std::expected: The class template std::expected provides a way to store either of two values. An object of std::expected at any given time either holds an expected value of type T, or an unexpected value of type E. std::expected is never valueless.

std::unexpected: The class template std::unexpected represents an unexpected value stored in std::expected.

std::expected, std::unexpected, .has_value(), .value(), .operator*

Example

#include <utxcpp/core.hpp>
#include <expected>

int main()
{
	std::expected<float, int> exp{123.5};
	utx::print(exp.value(), *exp); //123.5 123.5
	
	std::expected<float, int> exp2;
	utx::print(exp2.has_value(), exp2.value(), *exp2); //true 0.0 0.0
	
	exp2 = 3.14;
	if (exp2.has_value())
		utx::print(exp2.value()); //3.14
	
	// std::unexpected !
	exp2 = std::unexpected(9);
	utx::print(! exp2.has_value(), exp2 == std::unexpected(9)); //true true
}
.value_or, .swap

Example

#include <utxcpp/core.hpp>
#include <expected>

int main()
{
	std::expected<float, int> exp{2.5f};
	utx::print(exp.value_or(5.2f)); //2.5
	
	exp = std::unexpected(123);
	utx::print(exp.value_or(1.5f)); // 1.5
	
	exp = 7.2f;
	
	std::expected<float, int> exp2{9.3f};
	exp.swap(exp2);
	utx::print(exp.has_value(), exp.value(), exp2.has_value(), exp2.value()); //true 9.3 true 7.2
}
.operator->

Example

#include <utxcpp/core.hpp>
#include <expected>
#include <type_traits> // std::is_aggregate

class fizz_box
{
public:
	utx::f32 x{};
	utx::string y{};
public:
	void print() const
	{
		utx::print("(", x, ",", y, ")");
	}
};
static_assert(std::is_aggregate_v<fizz_box>);

int main()
{
	std::expected<fizz_box, std::string> exp{{1.2f, "c++20"}};
	
	utx::rt_assert(exp.has_value());
	exp->print(); // operator->
	
	exp = fizz_box{2.3f, "c++23"};
	utx::rt_assert(exp.has_value());
	exp->print(); // operator->
	
	exp = std::unexpected{"no value"};
	utx::rt_assert(! exp.has_value());
}

Top



New Header: <spanstream> std::spanstream

std::spanstream - The class template std::basic_spanstream implements input and output operations on streams based on fixed buffers.

At the low level, the class essentially wraps a raw device implementation of std::basic_spanbuf into a higher-level interface of std::basic_iostream. The complete interface to unique std::basic_spanbuf members is provided.

Typical implementations of std::basic_spanstream only add one member subobject: the wrapped std::basic_spanbuf.

std::basic_spanstream is derived from std::basic_iostream .

Example

#include <utxcpp/core.hpp>
#include <array>
#include <spanstream>
#include <span>
#include <string>

int main()
{
	std::array<char, 1024> array;
	std::span<char> span{array};
	std::spanstream spanstream{span};
	
	spanstream.write("c++23!", 6);
	utx::print_all(array); //c + + 2 3 !
	
	spanstream << 1024 << "c++23!";
	utx::print_all(array); //c + + 2 3 ! 1 0 2 4 c + + 2 3 !
	
	std::string str;
	str.resize(1024);
	std::spanstream ss{std::span<char>{str}};
	ss << "c++23!";
	
	utx::print_all(str); //c + + 2 3 !
	utx::print(str); //c++23!
	utx::print(str.data()); //c++23!
}

Top



std::invoke_r

template <class R, class F, class ... Args>
constexpr R invoke_r(F && f, Args && ... args) noexcept;

Usage:

auto r = std::invoke_r<R>(func, args ...);

Convert the result to type R, if it is convertible to R.

Example

#include <functional> // std::invoke, std::invoke_r
#include <utxcpp/core.hpp>
#include <string_view>

auto fn = [] (utx::u8 x, utx::u8 y) -> utx::u8
{
	return x+y;
};

int main()
{
	auto r1 = std::invoke(fn, 12, 100);
	auto r2 = std::invoke_r<utx::u16>(fn, 12, 100);
	
	utx::same_assert<decltype(r1), utx::u8, true>{};
	utx::same_assert<decltype(r2), utx::u8, false>{};
	utx::same_assert<decltype(r2), utx::u16, true>{};
	
	utx::rt_assert(std::cmp_equal(r1, r2));
}

Top



std::is_scoped_enum

std::is_scoped_enum

std::is_scoped_enum_v

Example

#include <utxcpp/core.hpp>
#include <type_traits> // std::is_scoped_enum, std::is_scoped_enum_v
#include <atomic>

class A;
enum class B;
enum C {};

int main()
{
	utx::print(
		std::is_scoped_enum_v<A>,
		std::is_scoped_enum_v<B>,
		std::is_scoped_enum_v<C>,
		std::is_scoped_enum_v<int>,
		std::is_scoped_enum_v<std::memory_order>
	);
	//false true false false true
}

Top



#elifdef #elifndef

Example

#include <utxcpp/core.hpp>

int main()
{
#ifdef b2
	utx::print("b2 build is used");
#elifdef bjam
	utx::print("bjam build is used");
#elifndef build
	utx::print("no build system");
#else
	utx::print("unknown build system");
#endif
}

Run:

b2
b2 -a define=b2
b2 -a define=bjam
b2 -a define=build

Top



std::unreachable

Invokes undefined behavior. An implementation may use this to optimize impossible code branches away (typically, in optimized builds) or to trap them to prevent further execution (typically, in debug builds).
https://en.cppreference.com/w/cpp/utility/unreachable

Example 1

#include <utxcpp/core.hpp>
#include <utility> // std::unreachable

namespace pk
{
	template <utx::kspt::real_number T>
	inline utx::fmax sqrt(const T & x)
	{
		if (x < 0)
		{
			utx::print("a");
			std::unreachable();
			utx::print("b");
		}
		utx::print("c");
		return std::sqrt<utx::fmax>(x).real();
	}
}

int main()
{
	utx::print(pk::sqrt(9));
	utx::print(pk::sqrt(-9));
}

/*
Output:
c
3.000000
a
c
0.000000
*/

Example 2

#include <utxcpp/core.hpp>
#include <utility> // std::unreachable

int fn(int x)
{
	switch (x)
	{
	case 1:
		[[fallthrough]];
	case 2:
		return 3;
	default:
		std::unreachable();
		return 7;
	}
	return 10;
}

int main()
{
	utx::print(fn(1));
	utx::print(fn(10000));
}

/*
Output:
3
9999
*/

Top



Attribute [[assume(expr)]]

Specifies that an expression will always evaluate to true at a given point.
https://en.cppreference.com/w/cpp/language/attributes/assume

Example

#include <utxcpp/core.hpp>

utx::i32 fn(utx::i32 x)
{
	[[assume(x>0)]];
	return ++x;
}

int main()
{
	fn(123); // more efficient
	fn(-123); // less efficient
}

Top



Related Links

Utxcpp Project

https://cppfx.xyz/fossil/utxcpp





cppreference c++23

https://en.cppreference.com/w/cpp/23





Boost c++ Libraries

https://www.boost.org





Top



























Last revised: March 27, 2023 at 03:21:19 GMT


PrevUpHomeNext