SFINEA的概念就是在模板的实例化过程中,如果一种实例方法匹配失败了,不会报错,而是继续寻找其它实例方法。
在最近的应用中,我碰到一个需要打印枚举的需求,打印枚举,一般的实现就是在打印枚举的函数里面写一个局部静态的哈希表(std::unordered_map),把枚举值和要输出的字符串一一对应。类似于这种:
static const char* Enum2Str(Format content) {
static auto && enum_map = []() {
EnumMap<Format> ret{ {Format::Red, "Format::Red"}};
return ret;
}();
return enum_map[content];
}
强枚举类型的哈希值可以利用std::is_enum来实现(或者我直接简单粗暴地static_cast成ull?)。
template <typename T, std::enable_if_t<std::is_enum<T>::value>* = nullptr>
static std::size_t Hash(T const& t) {
using base_type = typename std::underlying_type_t<T>;
return std::hash<base_type>()(static_cast<const base_type>(t));
}
template <typename T, std::enable_if_t<!std::is_enum<T>::value>* = nullptr>
static std::size_t Hash(T const& t) {
return std::hash<T>(t);
}
struct enum_hash{
template <typename T>
std::size_t operator()(const T&val)const {
return Hash<T>(val);
}
};
template <typename T>
using EnumMap = std::unordered_map<T, const char *, enum_hash>;
但我碰到的这个,不同的命名空间里面有类似的枚举类型,他们的枚举成员不尽相同。举个栗子,有几个命名空间里的“颜色”“格式”,我这里直接用相同名字+不同编号表示了。每种“颜色”枚举包含的颜色种类不一,每种“格式”类型包含的后缀名也不尽相同。如果命名空间有很多,那么为这一系列的“颜色”“格式”一个个写打印函数肯定存在很多重复代码。但是他们拥有的“颜色”“格式”有可能不一样,不可能一步到位,那样会编不过的。因此需要用到SFINAE。
// 不同的颜色空间
enum class Color0 {
Red,
Black,
Green
};
enum class Color1 {
White,
Black,
Purple
};
enum class Colo