无法使用 enable_if 和 is_base_of 区分模板特化

Vin*_*tDM 2 c++ enable-if template-meta-programming

我正在尝试将一些运行时检查换成编译时检查,以识别具有模板特化的对象的基类。

代码编译得很好,但我不明白为什么enable_if语句总是以无效或等于结束,void因为我总是登陆基本模板结构。

#include <iostream>
#include <type_traits>
using namespace std;

struct BaseOne {};
struct DerivedOne : BaseOne {};
struct BaseTwo {};
struct DerivedTwo : BaseTwo {};
struct Default {};

template<typename T, typename = void>
struct get_category_impl {
    static constexpr int value = 0;
};

template<typename T>
struct get_category_impl<T, typename enable_if<is_base_of<BaseOne, T>::value, T>::type> {
    static constexpr int value = 1;
};

template<typename T>
struct get_category_impl<T, typename enable_if<is_base_of<BaseTwo, T>::value, T>::type> {
    static constexpr int value = 2;
};

template<typename T>
constexpr int get_category = get_category_impl<T>::value;

int main() {
    cout << get_category<BaseOne>    << "\n"; // prints 0
    cout << get_category<DerivedOne> << "\n"; // prints 0
    cout << get_category<BaseTwo>    << "\n"; // prints 0
    cout << get_category<DerivedTwo> << "\n"; // prints 0
    cout << get_category<Default>    << "\n"; // prints 0
}
Run Code Online (Sandbox Code Playgroud)

cig*_*ien 5

enable_if不需要指定第二个参数 to 。如果您确实指定了它,它需要以某种方式解析为void. 由于您已将第二个参数指定为T,因此这不起作用。

相反,只需这样做:

template<typename T>
struct get_category_impl<T, typename enable_if<is_base_of<BaseOne, T>::value>::type> {
                                                                         // ^  No T 
    static constexpr int value = 1;
};
Run Code Online (Sandbox Code Playgroud)

其他专业也类似。

这是一个演示