Expand description
§Module :: clone_dyn_types
Core traits and logic for clone_dyn
.
This crate provides the core traits and logic for enabling cloning of trait objects, used by the clone_dyn
crate. It is an internal dependency and should not be used directly. Instead, use the clone_dyn
crate, which serves as a facade and includes this crate.
§Alternative
There are few alternatives dyn-clone, dyn-clonable. Unlike other options, this solution is more concise and demands less effort to use, all without compromising the quality of the outcome.
§Basic use-case
Demonstrates the usage of clone_dyn
to enable cloning for trait objects.
By default, Rust does not support cloning for trait objects due to the Clone
trait
requiring compile-time knowledge of the type’s size. The clone_dyn
crate addresses
this limitation through procedural macros, allowing for cloning collections of trait objects
and crate clone_dyn_types
contains implementation of all types.
§Overview
This example shows how to use the clone_dyn
crate to enable cloning for trait objects,
specifically for iterators. It defines a custom trait, IterTrait
, that encapsulates
an iterator with specific characteristics and demonstrates how to use CloneDyn
to
overcome the object safety constraints of the Clone
trait.
§The IterTrait
Trait
The IterTrait
trait is designed to represent iterators that yield references to items (&'a T
).
These iterators must also implement the ExactSizeIterator
and DoubleEndedIterator
traits.
Additionally, the iterator must implement the CloneDyn
trait, which allows cloning of trait objects.
The trait is implemented for any type that meets the specified requirements.
§Cloning Trait Objects
Rust’s type system does not allow trait objects to implement the Clone
trait directly due to object safety constraints.
Specifically, the Clone
trait requires knowledge of the concrete type at compile time, which is not available for trait objects.
The CloneDyn
trait from the clone_dyn_types
crate provides a workaround for this limitation by allowing trait objects to be cloned.
The example demonstrates how to implement Clone
for boxed IterTrait
trait objects.
§get_iter
Function
The get_iter
function returns a boxed iterator that implements the IterTrait
trait.
If the input is Some
, it returns an iterator over the vector.
If the input is None
, it returns an empty iterator.
It’s not possible to use impl Iterator
here because the code returns iterators of two different types:
std::slice::Iter
when the input isSome
.std::iter::Empty
when the input isNone
.
To handle this, the function returns a trait object ( Box< dyn IterTrait >
).
However, Rust’s Clone
trait cannot be implemented for trait objects due to object safety constraints.
The CloneDyn
trait addresses this problem by enabling cloning of trait objects.
§use_iter
Function
The use_iter
function demonstrates the use of the CloneDyn
trait by cloning the iterator.
It then iterates over the cloned iterator and prints each element.
§Main Function
The main function demonstrates the overall usage by creating a vector, obtaining an iterator, and using the iterator to print elements.
#[ cfg( not( feature = "enabled" ) ) ]
fn main() {}
#[ cfg( feature = "enabled" ) ]
fn main()
{
use clone_dyn_types::CloneDyn;
/// Trait that encapsulates an iterator with specific characteristics, tailored for your needs.
pub trait IterTrait< 'a, T >
where
T : 'a,
Self : Iterator< Item = T > + ExactSizeIterator< Item = T > + DoubleEndedIterator,
Self : CloneDyn,
{
}
impl< 'a, T, I > IterTrait< 'a, T > for I
where
T : 'a,
Self : Iterator< Item = T > + ExactSizeIterator< Item = T > + DoubleEndedIterator,
Self : CloneDyn,
{
}
// Implement `Clone` for boxed `IterTrait` trait objects.
impl< 'c, T > Clone for Box< dyn IterTrait< 'c, T > + 'c >
{
#[ inline ]
fn clone( &self ) -> Self
{
clone_dyn_types::clone_into_box( &**self )
}
}
///
/// Function to get an iterator over a vector of integers.
///
/// This function returns a boxed iterator that implements the `IterTrait` trait.
/// If the input is `Some`, it returns an iterator over the vector.
/// If the input is `None`, it returns an empty iterator.
///
/// Rust's type system does not allow trait objects to implement the `Clone` trait directly due to object safety constraints.
/// Specifically, the `Clone` trait requires knowledge of the concrete type at compile time, which is not available for trait objects.
///
/// In this example, we need to return an iterator that can be cloned. Since we are returning a trait object ( `Box< dyn IterTrait >` ),
/// we cannot directly implement `Clone` for this trait object. This is where the `CloneDyn` trait from the `clone_dyn_types` crate comes in handy.
///
/// The `CloneDyn` trait provides a workaround for this limitation by allowing trait objects to be cloned.
/// It uses procedural macros to generate the necessary code for cloning trait objects, making it possible to clone collections of trait objects.
///
/// It's not possible to use `impl Iterator` here because the code returns iterators of two different types:
/// - `std::slice::Iter` when the input is `Some`.
/// - `std::iter::Empty` when the input is `None`.
///
/// To handle this, the function returns a trait object (`Box<dyn IterTrait>`).
/// However, Rust's `Clone` trait cannot be implemented for trait objects due to object safety constraints.
/// The `CloneDyn` trait addresses this problem by enabling cloning of trait objects.
///
pub fn get_iter< 'a >( src : Option< &'a Vec< i32 > > ) -> Box< dyn IterTrait< 'a, &'a i32 > + 'a >
{
match &src
{
Some( src ) => Box::new( src.iter() ),
_ => Box::new( core::iter::empty() ),
}
}
/// Function to use an iterator and print its elements.
///
/// This function demonstrates the use of the `CloneDyn` trait by cloning the iterator.
/// It then iterates over the cloned iterator and prints each element.
pub fn use_iter< 'a >( iter : Box< dyn IterTrait< 'a, &'a i32 > + 'a > )
{
// Clone would not be available if CloneDyn is not implemented for the iterator.
// And being an object-safe trait, it can't implement Clone.
// Nevertheless, thanks to CloneDyn, the object is clonable.
//
// This line demonstrates cloning the iterator and iterating over the cloned iterator.
// Without `CloneDyn`, you would need to collect the iterator into a container, allocating memory on the heap.
iter.clone().for_each( | e | println!( "{e}" ) );
// Iterate over the original iterator and print each element.
iter.for_each( | e | println!( "{e}" ) );
}
// Create a vector of integers.
let data = vec![ 1, 2, 3 ];
// Get an iterator over the vector.
let iter = get_iter( Some( &data ) );
// Use the iterator to print its elements.
use_iter( iter );
}
If you use multithreading or asynchronous paradigms implement trait `Clone` also for `Send` and `Sync`
#[ allow( non_local_definitions ) ]
impl< 'c, T > Clone for Box< dyn IterTrait< 'c, T > + 'c >
{
#[ inline ]
fn clone( &self ) -> Self
{
clone_dyn_types::clone_into_box( &**self )
}
}
#[ allow( non_local_definitions ) ]
impl< 'c, T > Clone for Box< dyn IterTrait< 'c, T > + Send + 'c >
{
#[ inline ]
fn clone( &self ) -> Self
{
clone_dyn_types::clone_into_box( &**self )
}
}
#[ allow( non_local_definitions ) ]
impl< 'c, T > Clone for Box< dyn IterTrait< 'c, T > + Sync + 'c >
{
#[ inline ]
fn clone( &self ) -> Self
{
clone_dyn_types::clone_into_box( &**self )
}
}
#[ allow( non_local_definitions ) ]
impl< 'c, T > Clone for Box< dyn IterTrait< 'c, T > + Send + Sync + 'c >
{
#[ inline ]
fn clone( &self ) -> Self
{
clone_dyn_types::clone_into_box( &**self )
}
}
Try out cargo run --example clone_dyn_types_trivial
.
See code.
§To add to your project
cargo add clone_dyn_types
§Try out from the repository
git clone https://github.com/Wandalen/wTools
cd wTools
cd examples/clone_dyn_types_trivial
cargo run
Modules§
- dependency
- Namespace with dependencies.
- exposed
- Exposed namespace of the module.
- orphan
- Orphan namespace of the module.
- own
- Own namespace of the module.
- prelude
- Prelude to use essentials:
use my_module::prelude::*
.
Traits§
- Clone
Dyn - A trait to upcast a clonable entity and clone it. It’s implemented for all entities which can be cloned.
Functions§
- clone
- True clone which is applicable not only to clonable entities, but to trait objects implementing
CloneDyn
. - clone_
into_ box - Clone boxed dyn.