Last active
July 31, 2022 12:34
-
-
Save dlOuOlb/d86f78e8b2a28401b56700d67e9aead9 to your computer and use it in GitHub Desktop.
A class template about a buffer of uninitialized items.
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
#if __cplusplus < 202002L | |
# error "This code is written in C++20." | |
#else | |
export module dlOuOlb.containers:buffer; | |
import <concepts>; /* std::(regular|totally_ordered) */ | |
import <cstddef>; /* std::(ptrdiff|size)_t */ | |
import <iterator>; /* std::(\w+_)?iterator(_\w+)? */ | |
import <ranges>; /* std::ranges::\w+ */ | |
import <type_traits>; /* std::((conditional|remove_pointer)_t|is_(same|standard_layout|trivial)_v) */ | |
import <vector>; /* std::vector */ | |
namespace dlOuOlb::containers | |
{ | |
export template<class Type> concept buffee = std::is_trivial_v<Type> && std::regular<Type> && std::totally_ordered<Type>; | |
template<buffee Type> union item final | |
{ | |
Type _; | |
constexpr item( void ) noexcept // uninitialized members | |
{ | |
using Self = std::remove_pointer_t<decltype( this )>; | |
static_assert( alignof( Type ) == alignof( Self ) ); | |
static_assert( sizeof( Type ) == sizeof( Self ) ); | |
static_assert( std::is_standard_layout_v<Self> ); | |
static_assert( std::regular<Self> ); | |
static_assert( std::totally_ordered<Self> ); | |
return; | |
} | |
constexpr friend auto operator == ( const item<Type> &Former, const item<Type> &Latter )->bool { return Former._ == Latter._; } | |
constexpr friend auto operator <=> ( const item<Type> &Former, const item<Type> &Latter ) { return Former._ <=> Latter._; } | |
}; | |
export template<buffee Type> class buffer final : private std::vector<item<Type>> | |
{ | |
private: | |
using base = std::vector<item<Type>>; | |
static_assert( !base { }.capacity( ) ); | |
static_assert( std::is_same_v<std::size_t, base::size_type> ); | |
static_assert( std::is_same_v<std::ptrdiff_t, base::difference_type> ); | |
public: | |
using base::size_type; | |
using base::difference_type; | |
using value_type = Type; | |
using reference = value_type &; | |
using const_reference = const value_type &; | |
using pointer = value_type *; | |
using const_pointer = const value_type *; | |
using base::size; | |
using base::empty; | |
constexpr buffer( void ) noexcept = default; | |
buffer( const std::size_t Count ) : base { Count } | |
{ | |
using Self = std::remove_pointer_t<decltype( this )>; | |
static_assert( std::ranges::common_range<Self> ); | |
static_assert( std::ranges::contiguous_range<Self> ); | |
static_assert( std::ranges::sized_range<Self> ); | |
this->shrink_to_fit( ); | |
return; | |
} | |
constexpr auto data( void ) noexcept->pointer { return &this->base::data( )->_; } | |
constexpr auto data( void ) const noexcept->const_pointer { return &this->base::data( )->_; } | |
constexpr auto at( const std::size_t Index )->reference { return this->base::at( Index )._; } | |
constexpr auto at( const std::size_t Index ) const->const_reference { return this->base::at( Index )._; } | |
constexpr auto operator[ ]( const std::size_t Index )->reference { return this->base::operator[ ]( Index )._; } | |
constexpr auto operator[ ]( const std::size_t Index ) const->const_reference { return this->base::operator[ ]( Index )._; } | |
constexpr friend auto operator == ( const buffer<Type> &Former, const buffer<Type> &Latter )->bool { return static_cast<const base &>( Former ) == static_cast<const base &>( Latter ); } | |
constexpr friend auto operator <=> ( const buffer<Type> &Former, const buffer<Type> &Latter ) { return static_cast<const base &>( Former ) <=> static_cast<const base &>( Latter ); } | |
template<bool Const> class contiguous_iterator final | |
{ | |
public: | |
using iterator_category = std::contiguous_iterator_tag; | |
using difference_type = std::ptrdiff_t; | |
using element_type = std::conditional_t<Const, const value_type, value_type>; | |
constexpr contiguous_iterator( void ) noexcept = default; | |
constexpr contiguous_iterator( element_type *const _ ) noexcept : _ { _ } | |
{ | |
using Self = std::remove_pointer_t<decltype( this )>; | |
static_assert( std::contiguous_iterator<Self> ); | |
static_assert( std::random_access_iterator<std::reverse_iterator<Self>> ); | |
return; | |
} | |
constexpr friend auto operator <=> ( contiguous_iterator<Const>, contiguous_iterator<Const> ) noexcept = default; | |
constexpr auto operator *( void ) const->element_type & { return *this->_; } | |
constexpr auto operator->( void ) const noexcept->element_type * { return this->_; } | |
constexpr auto operator++( void ) noexcept->contiguous_iterator<Const> & { ++this->_; return *this; } | |
constexpr auto operator--( void ) noexcept->contiguous_iterator<Const> & { --this->_; return *this; } | |
constexpr auto operator++( const signed int ) noexcept->contiguous_iterator<Const> { return this->_++; } | |
constexpr auto operator--( const signed int ) noexcept->contiguous_iterator<Const> { return this->_--; } | |
constexpr auto operator[ ]( const difference_type Move ) const->element_type & { return this->_[ Move ]; } | |
constexpr auto operator+= ( const difference_type Move ) noexcept->contiguous_iterator<Const> & { this->_ += Move; return *this; } | |
constexpr auto operator-= ( const difference_type Move ) noexcept->contiguous_iterator<Const> & { this->_ -= Move; return *this; } | |
constexpr friend auto operator + ( const contiguous_iterator<Const> This, const difference_type Move ) noexcept->contiguous_iterator<Const> { return This._ + Move; } | |
constexpr friend auto operator + ( const difference_type Move, const contiguous_iterator<Const> This ) noexcept->contiguous_iterator<Const> { return This._ + Move; } | |
constexpr friend auto operator - ( const contiguous_iterator<Const> This, const difference_type Move ) noexcept->contiguous_iterator<Const> { return This._ - Move; } | |
constexpr friend auto operator - ( const contiguous_iterator<Const> This, const contiguous_iterator<Const> That ) noexcept->difference_type { return This._ - That._; } | |
private: | |
element_type *_; | |
}; | |
using iterator = contiguous_iterator<false>; | |
using const_iterator = contiguous_iterator<true>; | |
constexpr auto begin( void ) noexcept->iterator { return this->data( ); } | |
constexpr auto end( void ) noexcept->iterator { return this->data( ) + this->size( ); } | |
constexpr auto begin( void ) const noexcept->const_iterator { return this->cbegin( ); } | |
constexpr auto end( void ) const noexcept->const_iterator { return this->cend( ); } | |
constexpr auto cbegin( void ) const noexcept->const_iterator { return this->data( ); } | |
constexpr auto cend( void ) const noexcept->const_iterator { return this->data( ) + this->size( ); } | |
using reverse_iterator = std::reverse_iterator<iterator>; | |
using const_reverse_iterator = std::reverse_iterator<const_iterator>; | |
constexpr auto rbegin( void ) noexcept->reverse_iterator { return std::make_reverse_iterator( this->end( ) ); } | |
constexpr auto rend( void ) noexcept->reverse_iterator { return std::make_reverse_iterator( this->begin( ) ); } | |
constexpr auto rbegin( void ) const noexcept->const_reverse_iterator { return this->crbegin( ); } | |
constexpr auto rend( void ) const noexcept->const_reverse_iterator { return this->crend( ); } | |
constexpr auto crbegin( void ) const noexcept->const_reverse_iterator { return std::make_reverse_iterator( this->cend( ) ); } | |
constexpr auto crend( void ) const noexcept->const_reverse_iterator { return std::make_reverse_iterator( this->cbegin( ) ); } | |
}; | |
} | |
#endif |
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
#if __cplusplus < 202002L | |
# error "This code is written in C++20." | |
#else | |
export module dlOuOlb.containers; | |
export import:buffer; | |
#endif |
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
#if __cplusplus < 202002L | |
# error "This code is written in C++20." | |
#else | |
# include <format> /* std::format */ | |
# include <iostream> /* std::(cout|endl) */ | |
import dlOuOlb.containers; /* dlOuOlb::containers */ | |
extern R"(C++)" auto main( void ) noexcept( false )->signed int | |
{ | |
namespace S = std; | |
namespace OuO = dlOuOlb; | |
const auto Buffer = OuO::containers::buffer<unsigned char> { 8U }; // 8ZU in C++23 | |
for( const auto Item : Buffer ) | |
static_cast<void>( S::cout << S::format( R"({0:#X} )", Item ) ); // uninitialized reading | |
static_cast<void>( S::cout << S::endl ); | |
return 0; | |
} | |
#endif |
std::vector<bool>
may be a space-efficient specialization.dlOuOlb::buffer<bool>
is not a specialization; each element occupiessizeof(bool)
bytes.
dlOuOlb::buffee
requires TrivialType, Regular, and TotallyOrdered.dlOuOlb::buffer<dlOuOlb::buffee>
satisfies ContiguousContainer.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Tab-Size Preference: { default, 2, 3, 4, 6, 8 }