标准::条件与标准::enable_if
std::conditional vs std::enable_if
我有一个散列函数,可以接受任何对象类型并对其进行散列,它在内部使用std::hash
。由于std::hash
不支持枚举类型,因此我创建了函数的重载,1 用于使用 std::underlying_type
的枚举,1 用于其他类型的枚举:
template <typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
static std::size_t Hash(T const & t)
{
return std::hash<typename std::underlying_type<T>::type>()(t);
}
template <typename T, typename std::enable_if<!std::is_enum<T>::value>::type* = nullptr>
static std::size_t Hash(T const & t)
{
return std::hash<T>()(t);
}
这工作正常。然后我尝试将其全部放入一个具有std::conditional
的函数中:
template <typename T>
static std::size_t Hash(T const & t)
{
typedef typename std::conditional<std::is_enum<T>::value, std::hash<typename std::underlying_type<T>::type>, std::hash<T>>::type Hasher;
return Hasher()(t);
}
主要:
enum test
{
TEST = 2
};
int main() {
Hash<test>(TEST);
Hash<int>(5);
std::cin.get();
return 0;
}
但是,这给了我一个错误:
/usr/include/c++/5/type_traits:2190:38:错误:"int"不是枚举类型 类型定义 __underlying_type(_Tp) 类型;
我确实理解错误,但我不明白为什么,我认为std::conditional
可以防止这些编译时错误,因为<int>
在编译时使用std::hash<T>
而不是std::hash<typename std::underlying_type<T>::type>
。
我在这里做错了什么,有没有办法合并这两个功能?
如果模板参数不是枚举,则std::underlying_type
的格式不正确,并且std::conditional
的两个分支都需要有效。
一种可能性是创建一个safe_underlying_type
特征,如果T
不是枚举,则只返回void
:
template <typename T, typename = typename std::is_enum<T>::type>
struct safe_underlying_type {
using type = void;
};
template <typename T>
struct safe_underlying_type<T, std::true_type> {
using type = std::underlying_type_t<T>;
};
或者你可以只写一个特征来获取你想要的哈希类型:
template <typename T, typename = typename std::is_enum<T>::type>
struct hash_type {
using type = std::hash<T>;
};
template <typename T>
struct hash_type<T, std::true_type> {
using type = std::hash<std::underlying_type_t<T>>;
};
如果你真的想使用 conditional
,你需要推迟评估:
template<class T> struct identity { using type = T; };
using Hasher = std::hash<typename std::conditional<std::is_enum<T>::value,
std::underlying_type<T>,
identity<T>>::type::type>;
此外,自 LWG 2148 以来,std::hash
应该原生支持枚举。
typename std::underlying_type<T>::type
对于int
来说,它的格式并不好,但它在编译时仍然被计算。这就是您收到此错误的原因。您已经使用 std::enable_if
给出了解决方案,所以我不会在那里详细介绍。我认为这很好,无论如何使用std::conditional
只会使阅读变得更加困难。
conditional
中使用的两种类型(分支)在编译时都需要格式正确。
问题是,当编译器解析std::conditional
本身时,语句typename std::underlying_type<T>::type
需要格式正确(并且不适用于int
)。结果还是什么并不重要,它还没有走那么远。
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 我的简单if-else语句是如何无法访问的代码
- 如何将enable-if与模板参数和参数包一起使用
- 无论条件是否为true,if总是在c++中执行
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- 编译标准库类型
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- C++嵌套if语句,基本货币交换
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 是否可以使用if constexpr删除控制流语句
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 如何删除peer if else分支中的冗长句子
- "complicated-nested" "for/if statement"真的遵循C标准吗?
- 标准对单个 if 语句中单个变量的双重比较有什么看法
- 编译时已知条件下的标准if/else
- "if (getline(fin, str)) {}" 是否符合 C++11 标准?