In Rust you can implement traits for structs and each implementation has own type constraint. (for who may does not familiar with rust, you can consider a "trait" as a "base class" and "implementation" as "inheritance"). look at this example:
// our struct has an item of type mutable T pointer
struct Box<T> {
inner: mut* T
}
// implementing `Default` trait for
// box. in this implementation, type
// constraint is: `T: Default`.
// it means the inner type also must
// implements Default.
impl <T: Default> for Box<T> {
fn default() -> Self {
return Box::new(T::default());
}
}
the note in this example is there is no need T: Default to be applied until you use Box::default() in your code.
well it is possible to do like this in cpp? I'm familiar with how we can constraint types in cpp and this is not my problem. I want to know is there some way to lazy type constrain (maybe a better description) in cpp when I define a class?
I know it is possible with if constexpr or static_assert. but this way is not beautiful.
I want a template or concept solution ( I mean what applies to function signature in fact) if possible.
thank you for any guidance.
I am not sure I follow exactly what you want (I don't really know Rust), but you can constrain member functions individually:
Now
Boxitself has no requirements onT, but to useBox::default()will requireTto satisfy theDefaultconcept.However, it would basically work without the constraint as well. If
Box<T>::defaultcallsT::default()and the latter is not well-formed the code will fail to compile if and only ifBox<T>::defaultis actually used in a way that requires it to be defined (i.e. called or pointer/reference to it taken). But without therequiresclause e.g.Default<Box<T>>would always reporttrue.And of course in C++ we would use the default constructor instead of a static member function called
defaultto construct the object. The same approach applies to constructors though and there is already the conceptstd::default_initializablefor that in the standard library.As far as I understand, Rust traits do not really overlap fully with either C++ (abstract) base classes nor concepts though. The approach above will not allow for runtime polymorphism on types satisfying
Default. For that an abstract base class with the interface functions as non-static pure virtual member functions should be used instead.However, the trait
Defaultonly imposes a requirement on a static member function, so that it shouldn't be relevant to runtime polymorphism, but only compile-time properties of the type, which is what concepts are for, although in contrast to Rust you don't declare a type to implement a trait. Instead the concept describes requirements which a type needs to satisfy to satisfy the concept.