Ivan Smirnov
Ivan Smirnov

Reputation: 4435

Checking template parameter inheritance with SFINAE

I have a helper class R<T>, and some classes T inherit it. I want to declare some function f(T t) for those classes which do not inherit R<T>. This is done easily with SFINAE:

template<typename T>
class R {};

class Good : public R<Good> {};
class Bad {};

template<typename T>
auto f(T /* t */) -> typename std::enable_if<
    !std::is_base_of<R<T>, T>::value>::type
{
    // do something
}

int main() {
    f(Good()); // compilation error
    f(Bad()); // OK
}

Now I have some other class Derived which inherits Good. It does not inherit R<Derived> though. Still, I do not want to declare f(Derived).

class Derived : public Good {};

int main() {
    f(Derived()); // OK, but should be compilation error
}

So, what I want to check for type T is that T is a descendant of some R<P> where P is some parent of T.

Is it possible to do it with SFINAE? I'd like to stay within the scope of C++11.

Although I'm really interested in how to solve this general problem, in my exact case there is one simplification: I know that among all parents of T there is at most one R<P> for any P. Any solution for this simplification is also appreciated.

Upvotes: 2

Views: 210

Answers (1)

Ivan Smirnov
Ivan Smirnov

Reputation: 4435

Seems that I solved it, thanks to this answer:

template<template<typename> class Base, typename Derived>
struct SmartBaseOf {
private:
    template<class Intermediate>
    static auto test(const Base<Intermediate>&) -> typename std::enable_if<
            std::is_base_of<Intermediate, Derived>::value &&
                std::is_base_of<Base<Intermediate>, Intermediate>::value,
            std::true_type>::type;

    static std::false_type test(...);

public:
    constexpr static bool value = decltype(test(Derived()))::value;
};  

template<typename T>
auto f(T /* t */) -> typename std::enable_if<
    !SmartBaseOf<R, T>::value>::type
{   
    // do something
}   

Upvotes: 2

Related Questions