无法通过enable_if和is_base_of来区分模板专业化

问题描述

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

代码可以很好地编译,但是我无法弄清楚为什么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>::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
}

解决方法

enable_if的第二个参数不需要指定。如果您指定它,则需要以某种方式解析为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;
};

以及类似的其他专业化知识。

这里是demo