C++14 草案 n4140 阅读
T
shall be an enumeration type
template <class T> struct underlying_type
.
写的有多烂
std::conditional_t<std::is_enum<T>::value, std::underlying_type_t<T>, foo>
当T
可以是任意类型吗?我会进入 UB 并且编译器会删除我的 $HOME(因为语言律师说“在 UB 下任何事情都可能发生”)吗?
最佳答案
Will I step onto an UB [...]
从技术上讲,是的。但实际上,它不会针对非枚举类型进行编译。当你写:
std::conditional_t<std::is_enum<T>::value, std::underlying_type_t<T>, foo>;
^^^^^^^^^^^^^^^^^^^^^^^^^
必须在 conditional
之前评估该模板参数模板可以被实例化。这相当于必须在函数体开始之前调用所有函数参数。对于非枚举类型,underlying_type<T>
是不完整的(确保它在标准中被指定为未定义但让我们合理),所以没有 underlying_type_t
.所以实例化失败。
在这种情况下,您需要做的是延迟实例化:
template <class T> struct tag { using type = T; };
typename std::conditional_t<
std::is_enum<T>::value,
std::underlying_type<T>,
tag<foo>>::type;
现在,我们的 conditional
选择元函数而不是选择类型! underlying_type<T>::type
只会为 T
实例化作为一个枚举。我们还必须包装 foo
把它变成一个元函数。
这是一个常见的模式,在 Boost.MPL 中是一个特殊的东西,叫做 eval_if
,看起来像:
template <bool B, class T, class F>
using eval_if_t = typename std::conditional_t<B, T, F>::type;
请注意,我们都在使用 conditional_t
和 ::type
.
关于c++ - std::conditional 等 C++ 元函数的求值策略(eager、lazy 等)是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41267824/