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.
