مكتبة لتعدد الأشكال الديناميكي الفعال من خلال محو الكتابة (C++ 17 أو أحدث)
الأهداف هي الكفاءة وقابلية الفهم والتوسعة.
رنة، دول مجلس التعاون الخليجي، MSVC
How to build?
أساس جزء محو نوع المكتبة هو الأساليب - وصف أي جزء من النوع نريد استخدامه بعد المسح.
لنقم بإنشاء واحد لمحو الأنواع باستخدام void draw()
:
يوجد ماكرو anyany_method
في <anyany/anyany_macro.hpp> على سبيل المثال، بالنسبة للطريقة 'foo'، التي تقبل int وfloat + ترجع float
# include < anyany/anyany_macro.hpp >
anyany_method (foo, (&self, int i, float f) requires(self.foo(i, f)) -> float);
...
void example (aa::any_with<foo> obj) {
if (obj. has_value ())
float x = obj. foo ( 5 , 3 . 14f ); // all works
obj = some_type_with_foo{};
obj = some_other_type_with_foo ();
}
// For each type T do value.draw()
struct Draw {
template < typename T>
static void do_invoke ( const T& self) {
self. draw ();
}
};
يمكننا استخدام Draw
لمحو الكتابة:
# include < anyany/anyany.hpp >
using any_drawable = aa::any_with<Draw>;
والآن يمكننا استخدام any_drawable
لتخزين أي نوع باستخدام .draw()
// some types with .draw()
struct Circle {
void draw () const {
std::cout << " Draw Circle n " ;
}
};
struct Square {
void draw () const {
std::cout << " Draw Square n " ;
}
};
int main () {
any_drawable shape = Circle{};
aa::invoke<Draw>(shape); // prints "Draw Circle"
shape = Square{};
aa::invoke<Draw>(shape); // prints "Draw Square"
// see /examples folder for more
}
لا توجد وظائف افتراضية، وراثة، ومؤشرات، وإدارة الذاكرة وما إلى ذلك! لطيف - جيد!
يمكنك إضافة أي عدد من الطرق :
using any_my = aa::any_with<Draw, Run, aa::copy>;
انتظر، انسخ...؟ نعم، افتراضيًا تحتوي aa::any_with
على أداة تدمير فقط، ويمكنك إضافة طريقة aa::copy
لجعلها قابلة للنسخ والنقل أو aa::move
لجعلها متحركة فقط
طرق محددة مسبقا:
يجعل any_with
قابلاً للنسخ والنقل، ويمكّن aa::materialize
للمراجع (وهذا يتطلب أيضًا طريقة aa::destroy
)
هناك أيضًا copy_with<Alloc, SooS>
، وهذا يتيح النسخ عند استخدام المخصص المخصص وحجم تحسين الكائنات الصغيرة ( aa::basic_any_with
)
يجعل "any_with" متحركًا
ملاحظة: انقل المنشئ وانقل عامل التعيين any_with
عدم وجود استثناء دائمًا
يمكّن تخصص std::hash
لـ any_with
و poly_ref
/...إلخ. إذا كان any_with
فارغًا، فسيكون التجزئة == 0.
ملحوظة: يحتوي poly_ptr
على تخصص std::hash
بشكل افتراضي، ولكنه تجزئة تشبه المؤشر.
يمكّن aa::any_cast
و aa::type_switch
و aa::visit_invoke
عن طريق إضافة RTTI في vtable.
يضيف أيضًا .type_descriptor() -> aa::descriptor_t
لـ any_with
/ poly_ref
/...إلخ.
تمكين operator==
لـ any_with
/ poly_ref
/...إلخ.
هناك كائنان متساويان إذا كانا يحتويان على نفس النوع (أو كلاهما فارغًا) وكانت القيم المخزنة متساوية.
تمكين operator<=>
وعامل operator==
لـ any_with
/ poly_ref
/...إلخ.
ملاحظة: يقوم عامل التشغيل<=> دائمًا بإرجاع std::partial_ordering
.
إذا لم يحتوي كائنان على نفس النوع، فسيتم إرجاع unordered
، وإلا فسيتم إرجاع نتيجة operator <=>
للكائنات المضمنة.
ملاحظة: يتم إرجاع std::partial_ordering::equivalent
إذا كان كلاهما فارغًا
يضيف R operator()(Args...)
any_with
/ poly_ref
/...إلخ.
ملاحظة: يدعم أيضًا التوقيعات const
و noexcept
و const noexcept
مثال:
// stateful::cref is a lightweight thing,
// it stores vtable in itself(in this case only one function ptr)
// and const void* to value
// This is most effective way to erase function
template < typename Signature>
using function_ref = aa::stateful::cref<aa::call<Signature>>;
void foo (function_ref< int ( float ) const > ref) {
int result = ref ( 3.14 );
}
يضيف destructor (يمتلكه any_with
بشكل افتراضي)، ولكن ربما تريد استخدامه مع aa::poly_ptr
لإدارة مدى الحياة يدويًا. يمكّن أيضًا aa::materialize
للمراجع (يتطلب أيضًا aa::copy)
راجع مفهوم method
في Anyany.hpp إذا كنت تريد جميع التفاصيل حول الأساليب
أنواع متعددة الأشكال:
any_with<Methods...>
basic_any_with<Methods...>
poly_ref<Methods...>
poly_ptr<Methods...>
cref<Methods...>
cptr<Methods...>
stateful::ref<Methods...>
stateful::cref<Methods...>
الإجراءات:
any_cast<T>
invoke<Method>
type_switch
visit_invoke
حاويات متعددة الأشكال:
variant_swarm<Ts...>
data_parallel_vector<T, Alloc>
template < typename T>
concept method = /* ... */ ; // see anyany.hpp
// true if type can be used as poly traits argument in any_cast / type_switch / visit_invoke etc
template < typename T>
concept poly_traits = requires(T val, int some_val) {
{ val. get_type_descriptor (some_val) } -> std::same_as< descriptor_t >;
{ val. to_address (some_val) };
};
يمكنك تحديد السمات للتسلسلات الهرمية متعددة الأشكال الخاصة بك (معرفات الأنواع الشبيهة بـ LLVM والوظائف الفيروسية وما إلى ذلك).
تحتوي المكتبة على سمتين مدمجتين (يمكنك استخدامهما كمثال لتنفيذ السمات الخاصة بك):
على سبيل المثال، تريد أن يكون لديك الطريقة .foo() في النوع الذي تم إنشاؤه بواسطة any_with
أو poly_ref
باستخدام الطريقة الخاصة بك.
ثم يجب عليك استخدام plugins
:
struct Foo {
template < typename T>
static void do_invoke (T&) { /* do something */ }
// any_with<Foo> will inherit plugin<any_with<Foo>>
template < typename CRTP>
struct plugin {
void foo () const {
auto & self = * static_cast < const CRTP*>( this );
// Note: *this may not contain value, you can check it by calling self.has_value()
aa::invoke<Foo>(self);
}
};
};
//
any_with<Foo> val = /* ... */ ;
val.foo(); // we have method .foo from plugin!
ملاحظة: يمكنك "تظليل/تجاوز" المكونات الإضافية الأخرى عن طريق الوراثة منها في المكون الإضافي الخاص بك (حتى لو كان الوراثة خاصًا)
راجع aa::spaceship/aa::copy_with plugins على سبيل المثال
كما يمكنك تخصيص aa::plugin<Any, Method> لطريقتك أو حتى لـ "Any" مع بعض المتطلبات
any_with
يقبل أي عدد من الأساليب وينشئ نوعًا يمكنه الاحتفاظ بأي قيمة ويدعم تلك الأساليب . على غرار مفهوم وقت التشغيل
ملاحظة: هناك علامة 'aa::force_stable_pointers' لفرض التخصيص، لذلك لن يتم إبطال poly_ptr/cptr
إلى any_with<...>
بعد النقل.
ملاحظة: aa::unreachable_allocator
، والذي سيؤدي إلى قطع عملية الترجمة، إذا حاول basic_any_with<unreachable_allocator, ...>
تخصيص الذاكرة. حتى تتمكن من فرض عدم التخصيص في الأنواع
// All constructors and move assign operators are exception safe
// move and move assign always noexcept
// See 'construct_interface' alias in anyany.hpp and 'struct plugin'for details how it works(comments)
struct Any : construct_interface<basic_any<Alloc, SooS, Methods...>, Methods...>{
// aliases to poly ref/ptr
using ptr = /* ... */ ;
using ref = /* ... */ ;
using const_ptr = /* ... */ ;
using const_ref = /* ... */ ;
// operator & for getting poly ptr
poly_ptr<Methods...> operator &() noexcept ;
const_poly_ptr<Methods...> operator &() const noexcept ;
// main constructors
// creates empty
constexpr Any ();
Any ( auto && value); // from any type
Any ( const Any&) requires aa::copy
Any& operator =( const Any&) requires aa::move and aa::copy
Any (Any&&) noexcept requires aa::move;
Any& operator =(Any&&) requires method aa::move;
// observers
bool has_value () const noexcept ;
// returns true if poly_ptr/ref to *this will not be invalidated after moving value
bool is_stable_pointers () const noexcept
// returns count of bytes sufficient to store current value
// (not guaranteed to be smallest)
// return 0 if !has_value()
size_t sizeof_now() const noexcept ;
// returns descriptor_v<void> if value is empty
type_descriptor_t type_descriptor () const noexcept requires aa::type_info;
// forces that after creation is_stable_pointers() == true (allocates memory)
template < typename T>
Any ( force_stable_pointers_t , T&& value);
// also emplace constructors(std::in_place_type_t<T>), initiaizer list versions
// same with force_stable_pointers_t tag etc etc
// same with Alloc...
// modifiers
// emplaces value in any, if exception thrown - any is empty(use operator= if you need strong exception guarantee here)
template < typename T, typename ... Args>
std:: decay_t <T>& emplace (Args&&...); // returns reference to emplaced value
template < typename T, typename U, typename ... Args>
std:: decay_t <T>& emplace (std::initializer_list<U> list, Args&&... args)
// postcondition: has_value() == false
void reset() noexcept ;
// see aa::equal_to description for behavior
bool operator ==( const Any&) const requires aa::spaceship || aa::equal_to;
// see aa::spaceship description for behavior
std::partial_ordering operator <=>( const Any&) const requires aa::spaceship;
// ... interface from plugins for Methods if presented ...
};
يتمتع جميع المنشئين ومشغلي مهام النسخ/النقل بضمان استثناء قوي
ملاحظة: إذا كان النوع الخاص بك لا يحتوي على مُنشئ الحركة، فيمكنه بالفعل زيادة الأداء (كما هو الحال في حالة std::vector).
مثال:
using any_printable = aa::any_with<Print, aa::move>;
basic_any_with
تمامًا مثل any_with
، ولكن مع التخصيص المخصص وحجم المخزن المؤقت لتحسين الكائنات الصغيرة - إذا كنت بحاجة إلى basic_any_with
قابل للنسخ، فاستخدم copy_with
template < typename Alloc, size_t SooS, TTA... Methods>
using basic_any_with = /* ... */ ;
poly_ref
غير مالك، دائمًا ليس فارغًا، خفيف الوزن(~=باطل*)
poly_ref<Methods...>
يمكن تحويله ضمنيًا إلى عدد أصغر من الأساليب.
يمكن تحويل poly_ref<A, B, C>
إلى poly_ref<A, B>
, poly_ref<A>
, poly_ref<B>
... إلخ.
هذا يعني أنه يمكنك إضافة في واجهة الوظائف فقط الطرق التي تتطلبها حقًا. ثم إذا قمت بإضافة طريقة إلى نوع any_with
الخاص بك، فلن يكون هناك أي فاصل أبي/API.
// you can invoke this function with any poly_ref<..., A, ...>
void foo (poly_ref<A>);
template < template < typename > typename ... Methods>
struct poly_ref {
poly_ref ( const poly_ref&) = default ;
poly_ref (poly_ref&&) = default ;
poly_ref& operator =(poly_ref&&) = default ;
poly_ref& operator =( const poly_ref&) = default ;
// only explicit rebind reference after creation
void operator =( auto &&) = delete ;
descriptor_t type_descriptor () const noexcept requires aa::type_info;
// from mutable lvalue
template <not_const_type T> // not shadow copy ctor
poly_ref (T& value) noexcept
poly_ptr<Methods...> operator &() const noexcept ;
// ... interface from plugins for Methods if presented ...
}
const_poly_ref
مثل poly_ref
، ولكن يمكن إنشاؤه من poly_ref
و const T&
aa::cref
هو قالب مستعار لـ aa::const_poly_ref
ملحوظة: لا يمتد العمر
poly_ptr
غير مالك، لاغٍ، خفيف الوزن (~=باطل*)
poly_ptr<Methods...>
يمكن تحويله ضمنيًا إلى عدد أصغر من الأساليب.
يمكن تحويل poly_ptr<A, B, C>
إلى poly_ptr<A, B>
و poly_ptr<A>
و poly_ptr<B>
... إلخ.
هذا يعني أنه يمكنك إضافة في واجهة الوظائف فقط الطرق التي تتطلبها حقًا. ثم إذا قمت بإضافة طريقة إلى نوع any_with
الخاص بك، فلن يكون هناك أي فاصل أبي/API.
// you can invoke this function with any poly_ptr<..., A, ...>
void foo (poly_ptr<A>);
ملاحظة: poly_ptr
و const_poly_ptr
قابلان للنسخ بشكل تافه، لذلك يعمل std::atomic<poly_ptr<...>>
.
template < template < typename > typename ... Methods>
struct poly_ptr {
poly_ptr () = default ;
poly_ptr (std:: nullptr_t ) noexcept ;
poly_ptr& operator =(std:: nullptr_t ) noexcept ;
poly_ptr (not_const_type auto * ptr) noexcept ;
// from non-const pointer to Any with same methods
template <any_x Any>
poly_ptr (Any* ptr) noexcept ;
// observers
// returns raw pointer to value
void * raw () const noexcept ;
// NOTE: returns unspecified value if *this == nullptr
const vtable<Methods...>* raw_vtable_ptr () const noexcept ;
// returns descriptor_v<void> is nullptr
descriptor_t type_descriptor () const noexcept requires aa::type_info;
bool has_value () const noexcept ;
bool operator ==(std:: nullptr_t ) const noexcept ;
explicit operator bool () const noexcept ;
// similar to common pointer operator* returns reference
poly_ref<Methods...> operator *() const noexcept ;
const poly_ref<Methods...>* operator ->() const noexcept ;
}
const_poly_ptr
مثل poly_ptr
، ولكن يمكن إنشاؤه من poly_ptr
و const T*
/ Any*
aa::cptr
هو قالب مستعار لـ aa::const_poly_ptr
stateful_ref
aa::stateful::ref<Methods...>
يحتوي على vtable في حد ذاته.
يمكن أيضًا أن تحتوي على إشارات إلى مصفوفات C ووظائفها بدون تسوس
يحتوي على واجهة بسيطة جدًا، حيث يتم الإنشاء فقط من T&/poly_ref
والاستدعاء (بواسطة aa::invocation على سبيل المثال)
سيكون له أقصى قدر من الأداء إذا كنت بحاجة إلى مسح 1-2 طريقة ولا تحتاج إلى استخدام any_cast
.
حالة الاستخدام النموذجية - إنشاء function_ref
template < typename Signature>
using function_ref = aa::stateful::cref<aa::call<Signature>>;
bool foo ( int ) { return true ; }
void example (function_ref< bool ( int ) const > ref) {
ref ( 5 );
}
int main () {
example (&foo);
example ([]( int x) { return false ; });
}
stateful_cref
مثل stateful::ref
، لكن يمكن إنشاؤها من const T&
و aa::cref
any_cast
يتطلب طريقة aa::type_info
كائن وظيفي مع عامل التشغيل ():
يعمل كـ std::any_cast - يمكنك التحويل إلى T(copy)، وT&(take ref) (يرمي aa::bad_cast إذا كان الإرسال سيئًا)
أو يمكنك تمرير المؤشر (أو poly_ptr) (إرجاع nullptr، إذا كان الإرسال سيئًا)
T* ptr = any_cast<T>(&any);
مثال:
using any_comparable = aa::any_with<aa::copy, aa::spaceship, aa::move>;
void Foo () {
any_comparable value = 5 ;
value. emplace <std::vector< int >>({ 1 , 2 , 3 , 4 }); // constructed in-place
// any_cast returns pointer to vector<int>(or nullptr if any do not contain vector<int>)
aa::any_cast<std::vector< int >>( std::addressof (value))-> back () = 0 ;
// version for reference
aa::any_cast<std::vector< int >&>(value). back () = 0 ;
// version which returns by copy (or move, if 'value' is rvalue)
auto vec = aa::any_cast<std::vector< int >>(value);
}
invoke
كائن وظيفي مع عامل التشغيل()، والذي يقبل any_with/ref/cref/stateful::ref/stateful::cref
كوسيطة أولى ثم جميع وسائط الطريقة ويستدعي الطريقة
إذا كان arg هو const any_with
أو cref
، فيُسمح فقط بالتوابع const .
الشرط المسبق: Any.has_value() == صحيح
مثال:
void example (any_with<Say> pet) {
if (!pet. has_value ())
return ;
// invokes Method `Say`, passes std::cout as first argument
aa::invoke<Say>(pet, std::cout);
}
void foo (std::vector<aa::poly_ref<Foo>> vec) {
// invokes Method `Foo` without arguments for each value in `vec`
std::ranges::for_each (vec, aa::invoke<Foo>);
}
type_switch
يحدد .case بناءً على النوع الديناميكي لوسيطة الإدخال ويستدعي visitor
بهذا النوع الديناميكي أو الوظيفة الافتراضية
يدعم أيضًا poly_traits
كوسيطة قالب ثانية، لذا فهو يدعم أي نوع لديك سمات متعددة له
template < typename Result = void , poly_traits Traits = anyany_poly_traits>
struct type_switch_fn {
type_switch_fn (poly_ref<...>);
// invokes Fn if T contained
template < typename T, typename Fn>
type_switch_impl& case_ (Fn&& f);
// If value is one of Ts... F invoked (invokes count <= 1)
template < typename ... Ts, typename Fn>
type_switch_impl& cases (Fn&& f);
// if no one case succeded invokes 'f' with input poly_ref argument
template < typename Fn>
Result default_ (Fn&& f);
// if no one case succeded returns 'v'
Result default_ (Result v);
// if no one case succeded returns 'nullopt'
std::optional<Result> no_default ();
};
مثال:
Result val = aa::type_switch<Result>(value)
.case_< float >(foo1)
.case_< bool >(foo2)
.cases< char , int , unsigned char , double >(foo3)
.default_( 15 );
visit_invoke
إنه... حل التحميل الزائد في وقت التشغيل! aa::make_visit_invoke<Foos...>
ينشئ كائن مجموعة التحميل الزائد باستخدام الأسلوب .resolve(Args...)
، الذي ينفذ تحليل التحميل الزائد بناءً على Args... أنواع وقت التشغيل.
يُرجع الحل nullopt
في حالة عدم وجود مثل هذه الوظيفة لقبول وسائط الإدخال
هذا المثال أساسي للغاية، راجع أيضًا /examples/visit_invoc_example.hpp للمزيد
مثال:
auto ship_asteroid = [](spaceship s, asteroid a) -> std::string { ... }
auto ship_star = [](spaceship s, star) -> std::string { ... }
auto star_star = [](star a, star b) -> std::string { ... }
auto ship_ship = [](spaceship a, spaceship b) -> std::string { ... }
// Create multidispacter
constexpr inline auto collision = aa::make_visit_invoke<std::string>(
ship_asteroid,
ship_star,
star_star,
ship_ship);
...
// Perform runtime overload resolution
std::optional<std::string> foo (any_with<A> a, any_with<B> b) {
return collision. resolve (a, b);
}
variant_swarm
محول حاوية متعدد الأشكال، يعمل كـ Container<std::variant<Types...>>
، ولكنه أكثر فعالية.
يدعم العمليات:
visit<Types...>(visitor)
- يستدعي visitor
بكل قيمة الأنواع Types
view<T>
- يُرجع مرجعًا إلى الحاوية لجميع القيم المخزنة من النوع T
الحاوية هي std::vector
بشكل افتراضي.
template < template < typename > typename Container, typename ... Ts>
struct basic_variant_swarm {
// modifiers
void swap (basic_variant_swarm& other) noexcept ;
friend void swap (basic_variant_swarm& a, basic_variant_swarm& b) noexcept ;
// selects right container and inserts [it, sent) into it
template <std::input_iterator It>
requires (tt::one_of<std:: iter_value_t <It>, std::ranges:: range_value_t <Container<Ts>>...>)
auto insert (It it, It sent);
// insert and erase overloads for each type in Ts...
using inserters_type::erase;
using inserters_type::insert;
// observe
bool empty () const noexcept ;
// returns count values, stored in container for T
template <tt::one_of<Ts...> T>
requires (std::ranges::sized_range<container_for<T>>)
auto count () const ;
template <std:: size_t I>
requires (std::ranges::sized_range<decltype(std::get<I>(containers))>)
auto count () const ;
// returns count of values stored in all containers
constexpr auto size () const requires(std::ranges::sized_range<container_for<Ts>> && ...);
// returns tuple of reference to containers #Is
template <std:: size_t ... Is>
auto view ();
template <std:: size_t ... Is>
auto view () const ;
// returns tuple of reference to containers for Types
template <tt::one_of<Ts...>... Types>
auto view ();
template <tt::one_of<Ts...>... Types>
auto view () const ;
// visit
// visits with 'v' and passes its results into 'out_visitor' (if result is not void)
template <tt::one_of<Ts...>... Types>
void visit (visitor_for<Types...> auto && v, auto && out_visitor);
// ignores visitor results
template <tt::one_of<Ts...>... Types>
void visit (visitor_for<Types...> auto && v);
// visits with 'v' and passes its results into 'out_visitor' (if result is not void)
void visit_all (visitor_for<Ts...> auto && v, auto && out_visitor);
// ignores visitor results
constexpr void visit_all (visitor_for<Ts...> auto && v);
template <tt::one_of<Ts...>... Types, std::input_or_output_iterator Out>
constexpr Out visit_copy (visitor_for<Types...> auto && v, Out out);
template <tt::one_of<Ts...>... Types, std::input_or_output_iterator Out>
constexpr Out visit_copy (Out out);
// visits with 'v' and passes its results into output iterator 'out', returns 'out" after all
template <std::input_or_output_iterator Out>
constexpr Out visit_copy_all (visitor_for<Ts...> auto && v, Out out);
// passes all values into 'out' iterator, returns 'out' after all
template <std::input_or_output_iterator Out>
constexpr Out visit_copy_all (Out out);
// ...also const versions for visit...
};
مثال:
aa::variant_swarm< int , double , std::string> f;
// no runtime dispatching here, its just overloads
f.inesrt( " hello world " );
f.insert( 5 );
f.insert( 3.14 );
auto visitor = []( auto && x) {
std::cout << x << ' t ' ;
};
f.visit_all(visitor); // prints 5, 3.14, "hello world"
data_parallel_vector
تتصرف هذه الحاوية كـ std::vector<T>
، ولكنها تخزن الحقول بشكل منفصل.
العملية المدعومة: view<T>
/ view<I>
للحصول على امتداد لجميع حقول هذا الفهرس
يجب أن يكون T
من النوع الكلي أو الشبيه بالصفوف
ملاحظة: data_parallel_vector
هو نطاق وصول عشوائي ملاحظة: يتجاهل التخصص std::vector<bool>
، ويتصرف كمتجه عادي للمنطقيات
template < typename T, typename Alloc>
struct data_parallel_vector {
using value_type = T;
using allocator_type = Alloc;
using difference_type = std:: ptrdiff_t ;
using size_type = std:: size_t ;
using reference = proxy; // similar to vector<bool>::reference type
using const_reference = const_proxy;
void swap (data_parallel_vector&) noexcept ;
friend void swap (data_parallel_vector&) noexcept ;
data_parallel_vector () = default ;
explicit data_parallel_vector ( const allocator_type& alloc);
data_parallel_vector (size_type count, const value_type& value,
const allocator_type& alloc = allocator_type());
explicit data_parallel_vector (size_type count, const allocator_type& alloc = allocator_type());
template <std::input_iterator It>
data_parallel_vector (It first, It last, const allocator_type& alloc = allocator_type());
data_parallel_vector ( const data_parallel_vector& other, const allocator_type& alloc);
data_parallel_vector (data_parallel_vector&& other, const allocator_type& alloc);
data_parallel_vector (std::initializer_list<value_type> init,
const allocator_type& alloc = allocator_type());
// copy-move all default
data_parallel_vector& operator =(std::initializer_list<T> ilist);
using iterator;
using const_iterator;
iterator begin ();
const_iterator begin () const ;
iterator end ();
const_iterator end () const ;
const_iterator cbegin () const ;
const_iterator cend () const ;
reference front ();
const_reference front () const ;
reference back ();
reference back () const ;
reference operator [](size_type pos);
const_reference operator [](size_type pos) const ;
size_type capacity () const ;
size_type max_size () const ;
// returns tuple of spans to underlying containers
template < typename ... Types>
auto view ();
template < typename ... Types>
auto view () const ;
template <std:: size_t ... Nbs>
auto view ();
template <std:: size_t ... Nbs>
auto view () const ;
bool empty () const ;
size_type size () const ;
bool operator ==( const data_parallel_impl&) const = default ;
iterator emplace (const_iterator pos, element_t <Is>... fields);
reference emplace_back ( element_t <Is>... fields);
void push_back ( const value_type& v);
void push_back (value_type&& v);
iterator erase (const_iterator pos);
iterator erase (const_iterator b, const_iterator e);
iterator insert (const_iterator pos, const value_type& value);
iterator insert (const_iterator pos, value_type&& value);
iterator insert (const_iterator pos, size_type count, const T& value);
template <std::input_iterator It>
iterator insert (const_iterator pos, It first, It last);
iterator insert (const_iterator pos, std::initializer_list<value_type> ilist);
void assign (size_type count, const value_type& value);
template <std::input_iterator It>
void assign (It first, It last);
void assign (std::initializer_list<T> ilist);
void clear ();
void pop_back ();
void reserve (size_type new_cap);
void resize (size_type sz);
void resize (size_type sz, const value_type& v);
void shrink_to_fit ();
};
مثال:
struct my_type {
int x;
float y;
bool l;
};
void foo () {
aa::data_parallel_vector<my_type> magic;
// ints, floats, bools are spans to all stored fields of my_type (&::x, &::y, &::l)
auto [ints, floats, bools] = magic;
magic. emplace_back ( 5 , 6 . f , true );
};
جلب المحتوى:
include (FetchContent)
FetchContent_Declare(
AnyAny
GIT_REPOSITORY https://github.com/kelbon/AnyAny
GIT_TAG origin/main
)
FetchContent_MakeAvailable(AnyAny)
target_link_libraries (MyTargetName anyanylib)
add_subdirectory (AnyAny)
target_link_libraries (MyTargetName PUBLIC anyanylib)
build
git clone https://github.com/kelbon/AnyAny
cd AnyAny
cmake . -B build
cmake --build build
git clone https://github.com/kelbon/AnyAny
cd AnyAny/examples
cmake . -B build