Home > Back-end >  force generic type of template function to inherit some class
force generic type of template function to inherit some class

Time:08-06

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.

  • Related