in Rust programing language you can declare a function with argument of generic type that must implement a trait. (for those who doesn't know, you can think implement
is inheritance
and trait
is class
). so the object you pass to that function must have that trait implemented. for example:
// Define a function `printer` that takes a generic type `T` which
// must implement trait `Display`.
fn printer<T: Display>(t: T) {
println!("{}", t);
}
now my question is, how can I define such template function in c that force a type to inherit some base classes?
CodePudding user response:
You can use std::is_base_of
to check if a type has a particular base class. Leveraging SFINAE that would look like:
template <typename T, std::enable_if_t<std::is_base_of_v<BASE_CLASS, T>, bool> = true>
ret_type function_name(T t)
{
// your code
}
The above template will only get instantiated if T
derives from BASE_CLASS
or is the same type.
CodePudding user response:
In C 20, you have requires
that simplifies this.
Since C 20 is not yet that widespreaded at the time of writing, here's an example that's backwards compatible:
template<typename T>
std::enable_if_t<std::is_base_of_v<Display, T>> fn(const T& t)
{
// your favorite println implementation over t
}
If you'd like to return a value, use std::enable_if_t<condition, return_type>
.
CodePudding user response:
The C 20 way:
template <std::derived_from<Display> T>
void printer(const T &value)
{
// ...
}
Or the abbreviated template syntax:
void printer(const std::derived_from<Display> auto &value)
{
// ...
}
Do note that there's some difference between std::derived_from
and std::is_base_of_v
(other than one of them being a concept): the latter checks for any base, while the former checks for an unambiguous public base. If that's what you want, but you don't have C 20, you can additionally check std::is_convertible_v<A *, B *>
for this.