You can return an enum:
enum StrOrStrAndVec<'a> {
Str(&'a str),
StrAndVec(&'a str, Vec<usize>),
}
fn f3(flag: bool) -> StrOrStrAndVec<'static> {
if flag {
StrOrStrAndVec::StrAndVec("abc", vec![0, 1, 2])
} else {
StrOrStrAndVec::Str("abc")
}
}
The either crate simplifies this approach:
use either::*;
fn f3(flag: bool) -> Either<&'static str, (&'static str, Vec<usize>)> {
if flag {
Right(("abc", vec![0, 1, 2]))
} else {
Left("abc")
}
}
Or, in this case you can use an Option:
fn f3(flag: bool) -> (&'static str, Option<Vec<usize>>) {
if flag {
("abc", Some(vec![0, 1, 2]))
} else {
("abc", None)
}
}
However, since Vec::new() doesn't allocate memory, returning an empty Vec is similarly efficient:
fn f3(flag: bool) -> (&'static str, Vec<usize>) {
if flag {
("abc", vec![0, 1, 2])
} else {
("abc", Vec::new())
}
}
Playground