I've been learning the concept of SFINAE in C++ recentlly and I am currentlly trying to use it in a project.
The thing is, what I'm trying to do is different than anything I could find, and I can't figure out how to do it.
Let's say I have a template class called MyParent:
template <typename Elem>
class MyParent;
And a non-template class called MyClass, that inherites it, using char as Elem:
class MyClass : public MyParent<char>;
Now, I want to use SFINAE in order to check if a typename inherites MyParent
, regardless of what Elem
type is used.
I can't use std::is_base_of
, because of the parent's template.
I've tried to do the following:
template <typename T>
struct is_my_parent : std::false_type {};
template <typename Elem>
struct is_my_parent<MyParent<Elem>> : std::true_type {};
Now, if I check for is_my_parent<MyParent<Elem>>::value
, it gives me true
. Which is good.
However, when I check for is_my_parent<MyClass>::value
, I recive false
. Which kind of makes sence because MyClass
isn't actually MyParent<Elem>
, but I didn't manage to get what I wanted.
Is there any convenient way to achive such a thing in C++, other than defining is_my_parent
for each and every class that inherites from MyParent
?
You might do
template <typename T>
std::true_type is_my_parent_impl(const MyParent<T>*);
std::false_type is_my_parent_impl(const void*);
template <typename T>
using is_my_parent = decltype(is_my_parent_impl(std::declval<T*>()));
Demo
Is there any convenient way to achive such a thing in C++, other than defining is_my_parent for each and every class that inherites from MyParent?
There is, but you'll need to use more elaborate meta-programming techniques. Go entirely back to basics, as it were.
template <class C>
class is_my_parent {
using yes = char;
using no = char[2];
template<typename t>
static yes& check(MyParent<t> const*);
static no& check(...);
public:
enum { value = (1 == sizeof check(static_cast<C*>(0))) };
};
It relies on two basic properties of function overloading and templates:
Then it's just a matter of inspecting the return type of the chosen overload to determine what we got. Other than the type alias, you can even use this in C++03. Or you can modernize it, so long as overload resolution does the work for you, the check will be performed just the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With