使用SFINAE检查模板参数继承

时间:2017-03-16 09:42:31

标签: c++ c++11 templates inheritance sfinae

我有一个帮助类R<T>,而某些类T继承它。我想为那些不继承f(T t)的类声明一些函数R<T>。这可以通过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
}

现在我有一些继承Derived的其他课程Good。它不会继承R<Derived>。不过,我不想宣布f(Derived)

class Derived : public Good {};

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

因此,我想要检查类型T的是T是某些R<P>的后代,其中PT的某个父级。

是否可以使用SFINAE?我希望保持在C ++ 11的范围内。

虽然我对如何解决这个一般性问题非常感兴趣,但在我的确切情况下有一个简化:我知道在T的所有父母中,最多只有一个R<P>对于任何P。任何解决这种简化的方法也很受欢迎。

1 个答案:

答案 0 :(得分:2)

似乎我解决了它,感谢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
}