C++26包索引
template<auto N> consteval auto nth(auto... ts) { return ts...[N]; }
static_assert(1 == nth<0>(1, 2, 3));
static_assert(2 == nth<1>(1, 2, 3));
static_assert(3 == nth<2>(1, 2, 3));
C++26包索引的第1和最后
template <size_t Index, class T0, class... Types>
constexpr decltype(auto) nth(T0&& p0, Types&&... pack) noexcept
{
if constexpr (0 == Index)
return std::forward<T0>(p0);
else
return nth<Index-1>(std::forward<Types>(pack)...);
}
consteval auto first(auto... ts) {
return nth<0>(ts...);
}
consteval auto last(auto... ts) {
return nth<sizeof...(ts) - 1>(ts...);
}
static_assert(1 == first(1, 2, 3));
static_assert(3 == last(1, 2, 3));
平映
int main() {
stdext::flat_map<int, int> fm{};
fm.emplace(1, 2);
fm.emplace(3, 4);
assert(fm.size() == 2);
assert(fm[1]==2 and fm[2]==3);
}
无唯一地址
template<class> struct box{};
struct unique {
[[no_unique_address]] box<int> _1;
[[no_unique_address]] box<bool> _2;
};
static_assert(sizeof(unique)==1);
struct no_unique {
[[no_unique_address]] box<int> _1;
[[no_unique_address]] box<int> _2;
};
static_assert(sizeof(no_unique)!=1);
是独特的
template <class T> struct box {};
template <class... Ts> struct unique;
template <>
struct unique<> {};
template <class T, class ...Args>
struct unique<T, Args ...> : public unique<Args ...> {
constexpr explicit unique(T&& t, Args&&... args) : unique<Args...>(args ...) {
}
[[no_unique_address]] box<T> t_;
};
template <class... Ts>
constexpr auto is_unique = (sizeof(unique<Ts...>) == 1);
template <typename T>
struct empty_wrap { };
template <typename T, typename = decltype([]() {})>
struct unique_empty_box {
[[no_unique_address]] empty_wrap<T> e;
};
template <typename... Ts>
struct empty_type_pack : public unique_empty_box<Ts>... { };
template <typename... Ts>
constexpr bool is_unique = sizeof(empty_type_pack<Ts...>) == 1;
template <class>
struct box {
box() = delete;
};
template <class... Ts>
struct S;
template <>
struct S<> {};
template <class T, class... Ts>
struct S<T, Ts...> : S<Ts...> {
[[no_unique_address]] box<T> _;
};
template <class... Ts>
constexpr auto is_unique = sizeof(S<Ts...>) == 1;
线本常初化
extern constinit thread_local int var;
auto fn() { return var; }
区间串视
constexpr std::string text = "Hello, World!";
constexpr std::string_view view(text.c_str() + 7, 5);
static_assert(view == std::string_view{"World"});
显式串视缓冲
template<auto N>
struct buffer; // TODO
constexpr buffer<42> b;
static_assert(42 == std::string_view{b}.size());
static_assert(&b.data[0] == std::string_view{b}.begin());
static_assert(&b.data[42] == std::string_view{b}.end());
template <auto N>
struct buffer {
constexpr buffer() {}
constexpr char const* begin() const { return data; }
constexpr char const* end() const { return data + N; }
constexpr operator std::basic_string_view<char>() const {
return std::basic_string_view<char>(begin(), end());
}
char data[N]{};
};
标::访问
template<class... Ts>
struct inc {
std::variant<Ts...> v{};
auto operator++() {
std::visit([&](auto& v) { ++v; }, v);
}
template<class T>
operator T() const {
T result{};
std::visit(
overloaded{
[&](T v) { result = v; },
[](auto&&) {}
}
, v);
return result;
}
};
auto visit(std::int16_t size, std::int32_t iterations) {
auto it = inc<std::int8_t, std::int16_t, std::int32_t>{size};
for (auto i = 0; i < iterations; ++i, ++it)
;
return std::int16_t(it);
}
实现:
template<class F, class V, class R, std::size_t N, std::size_t Size>
constexpr auto visit_impl([[maybe_unused]] F&& f, [[maybe_unused]] V&& v) -> R {
if constexpr (N < Size) {
switch (v.index()) {
default:
return visit_impl<F, V, R, N+1, Size>(std::forward<F>(f), std::forward<V>(v));
case N:
return std::forward<F>(f)(std::get<N>(std::forward<V>(v)));
}
} else {
__builtin_unreachable();
}
}
template<class F, class V, template<class...> class T, class... Ts>
auto result_type(T<Ts...>&&) ->
std::common_type_t<decltype(std::declval<F>()(std::get<Ts>(std::declval<V>())))...>;
template<class F, class V, template<class...> class T, class... Ts>
auto result_type(T<std::monostate, Ts...>&&) ->
std::common_type_t<decltype(std::declval<F>()(std::get<Ts>(std::declval<V>())))...>;
template<class F, class V>
constexpr decltype(auto) visit(F&& f, V&& v) {
using variant_t = std::remove_const_t<std::remove_reference_t<V>>;
constexpr auto size = std::variant_size_v<variant_t>;
static_assert(size > 0, "Empty variant is not supported!");
using result_t = decltype(result_type<F, V>(std::declval<variant_t>()));
return visit_impl<F, V, result_t, 0u, size>(std::forward<F>(f), std::forward<V>(v));
}
C++26可变友
class FriendClass;
class MyClass {
friend class FriendClass;
public:
constexpr MyClass(int data) : privateData(data) {}
private:
int privateData;
};
struct FriendClass {
constexpr auto accessPrivateData(const MyClass& obj) const {
return obj.privateData;
}
};
constexpr MyClass obj{42};
constexpr FriendClass friend_obj{};
static_assert(42 == friend_obj.accessPrivateData(obj));
扩展可变友类
template <class... Ts>
class MyClass {
friend Ts...;
public:
constexpr explicit MyClass(int data) : privateData(data) {}
private:
int privateData{};
};
template<auto>
struct FriendClass {
constexpr auto accessPrivateData(const auto& obj) const {
return obj.privateData;
}
};
constexpr MyClass<FriendClass<0>, FriendClass<1>, FriendClass<2>> obj{42};
constexpr FriendClass<0> friend_obj0{};
constexpr FriendClass<1> friend_obj1{};
constexpr FriendClass<2> friend_obj2{};
static_assert(42 == friend_obj0.accessPrivateData(obj));
static_assert(42 == friend_obj1.accessPrivateData(obj));
static_assert(42 == friend_obj2.accessPrivateData(obj));
原位向量
int main() {
std::inplace_vector<int, 2> v{};
assert(v.empty());
v.push_back(1);
assert(1 == v.size());
v.push_back(2);
assert(2 == v.size());
v.push_back(3); // throws
}
实现
template <class T, auto Size>
struct inplace_vector {
constexpr void push_back(T value) { data_[index_++] = value; }
constexpr const auto& operator[](auto index) const { return data_[index]; }
constexpr auto size() const { return index_; }
constexpr auto clear() { index_ = {}; }
private:
std::array<T, Size> data_{};
std::size_t index_{};
};
template <class T, auto Size>
class inplace_vector {
public:
constexpr T& push_back(const T& t) {
if (size_ == Size) {
throw std::bad_alloc();
}
return arr_[size_++].emplace(t);
}
constexpr std::size_t size() const { return size_; }
constexpr T& operator[](std::size_t idx) { return *arr_[idx]; }
private:
std::array<std::optional<T>, Size> arr_;
std::size_t size_ = 0;
};
聚集是命名元组
#include <tuple>
struct foo {
int i{};
bool b{};
float f{};
};
constexpr auto f = foo{.i = 42, .b = true, .f = 4.2f};
static_assert(42 == std::get<0>(f) and std::get<1>(f) and 4.2f == std::get<2>(f));
聚集的取
template <typename T, std::size_t I, typename = void>
struct has_get : std::false_type {};
template <typename T, std::size_t I>
struct has_get<T, I, std::void_t<decltype(std::get<I>(std::declval<T>()))>>
: std::true_type {};
namespace std {
template <typename T>
concept DoesNotHaveGetConcept = requires(T t) { !has_get<T, 0>::value; };
namespace mp = boost::mp;
template <std::size_t I>
constexpr auto get(DoesNotHaveGetConcept auto s) {
return std::get<I>(mp::reflection::to_tuple(s));
}
} // namespace std
更多数学常式
#include <cmath>
constexpr auto positive = std::abs(-2);
static_assert(positive == 2);
template <char... Cs>
[[nodiscard]] constexpr auto operator""_number() {
return []<auto... Is, class T = int>(std::index_sequence<Is...>) {
return std::integral_constant<
T, (((Cs - '0') * T(std::pow(T(10), sizeof...(Is) - Is - 1))) +
...)>{};
}
(std::make_index_sequence<sizeof...(Cs)>{});
}
#include <cmath>
template <char... Cs>
[[nodiscard]] constexpr auto operator""_number();
static_assert(0 == 0_number);
static_assert(42 == 42_number);
static_assert(123 == 123_number);
template <char... Cs>
[[nodiscard]] constexpr auto operator""_number() {
int result = 0;
((result = result * 10 + (Cs - '0')), ...);
return result;
}
C++26常式从空*
转换
struct foo{};
constexpr auto f1 = foo{};
constexpr auto ptr = static_cast<const void*>(&f1);
constexpr auto f2 = static_cast<const foo*>(ptr); // okay in C++26
常式擦除
struct Animal_View {
const void *animal;
std::string_view (*speak_func)(const void *animal);
template <class Animal>
Animal_View(const Animal &animal)
: animal(&animal), speak_func([](const void *animal) {
return static_cast<const Animal *>(animal)->speak();
}) {}
constexpr std::string_view speak() { return speak_func(animal); }
};
struct Sheep {
constexpr std::string_view speak() const noexcept { return "Baaaaaa"; }
};
struct Cow {
constexpr std::string_view speak() const noexcept { return "Mooo"; }
};
// TODO Animal_View
std::string_view do_speak(Animal_View av) { return av.speak(); }
int main() {
using namespace boost::ut;
"constexpr cast from void*"_test = [] {
should("say Mooo for cow") = [] {
constexpr Cow cow;
auto result = do_speak(cow);
expect(std::string_view{"Mooo"} == result);
};
should("say Baaaaaa for sheep") = [] {
constexpr Sheep sheep;
auto result = do_speak(sheep);
expect(std::string_view{"Baaaaaa"} == result);
};
};
}
成员访问
// C++23
std::visit(overload{
[](int i){ std::print("i={}\n", i); },
[](std::string s){ std::print("s={:?}\n", s); }
}, value);
// C++26
value.visit(overload{
[](int i){ std::print("i={}\n", i); },
[](std::string s){ std::print("s={:?}\n", s); }
});
变量成员访问
// TODO: variant
int main() {
constexpr variant<int, double, float> value = 42;
static_assert(42 == value.visit(overload{
[](int i) { return i; },
[](auto) { return 0; }
}));
}
template <class... Ts>
struct overload : Ts... {
using Ts::operator()...;
};
template <class... Ts>
overload(Ts...) -> overload<Ts...>;
template <class... Ts>
struct variant : std::variant<Ts...> {
using std::variant<Ts...>::variant;
constexpr auto visit(auto f) const { return std::visit(f, *this); }
};