Reputation: 103
I recently started using rust and am working on a library. The following works, but seems like code duplication
#[cfg(feature = "serde_support")]
use serde::Serialize;
#[cfg(not(feature = "serde_support"))]
pub struct Teststruct<T>
{
graph: T
}
#[cfg(feature = "serde_support")]
#[derive(Serialize)]
pub struct Teststruct<T>
where T: Serialize
{
graph: T
}
Note, that, while the trait bound where T: Serialize
in not strictly required in this example, it is required in the problem I am facing currently.
So the above looks like needless code duplication to me, especially if the structs contains more fields. I would rather write something like:
#[cfg(feature = "serde_support")]
use serde::Serialize;
#[cfg_attr(feature = "serde_support", derive(Serialize))]
pub struct Teststruct<T: Node>
where T: Serialize,
Graph<T>: Serialize + DeserializeOwned
{
graph: Graph<T>
}
Now, however, I can only compile with the feature "serde_support" - without the feature, I obviously get the error: Serialize
is not found in this scope.
I have tried to find something like cfg_attr for the trait bound, but to no avail.
Is there an elegant way to avoid the code duplication?
Upvotes: 10
Views: 1579
Reputation: 1674
Or just by using conditional compilation:
#[cfg_attr(feature = "serde_support", derive(Serialize))]
pub struct TestStruct<
#[cfg(feature = "serde_support")] T: serde::Serialize,
#[cfg(not(feature = "serde_support"))] T,
> {
graph: T
}
For some reason, you can't yet do this inside a where
block where it would look much nicer. (rustc 1.55.0-nightly)
Upvotes: 5
Reputation: 36081
You could introduce a new intermediate trait MySerialize
, so that you always require MySerialize
instead of Serialize
, thus doing this switch only in one place.
The derive could be solved via cfg_attr
.
#[cfg(feature = "serde_support")]
use serde::Serialize;
#[cfg(feature = "serde_support")]
pub trait MySerialize : Serialize {}
#[cfg(not(feature = "serde_support"))]
pub trait MySerialize {}
#[cfg_attr(feature = "serde_support", derive(Serialize))]
pub struct Teststruct<T>
where T: MySerialize
{
graph: T
}
Upvotes: 8