标签:temp typedef failure code ref 运算 lse for template
替换失败不是错误 (Substitution Failure Is Not An Error),此特性被用于模板元编程。
在函数模板的重载决议中应用此规则,当将模板形参替换为显式指定的类型或推导的类型失败时,从重载集中丢弃这个特化,而非导致编译失败。
类型特性 定义一个编译时基于模板的结构,以查询或修改类型的属性,是一种类型萃取技术。
type_traits 在 C++ 中是基于 SFINAE 实现的,通过模板的偏特化来查询或者修改类型的属性,无运行时开销。
其核心是整数常量模板 integral_constant
,MSVC 的实现如下:
template <class _Ty, _Ty _Val>
struct integral_constant { // convenient template for integral constant types
static constexpr _Ty value = _Val;
using value_type = _Ty;
using type = integral_constant;
constexpr operator value_type() const noexcept { // return stored value
return (value);
}
constexpr value_type operator()() const noexcept { // return stored value
return (value);
}
};
其实平平无奇,保存了类模板的类型和值而已,没有什么特殊的地方,现在将这个模板特化为bool类型
// ALIAS TEMPLATE bool_constant
template <bool _Val> using bool_constant = integral_constant<bool, _Val>;
using true_type = bool_constant<true>;
using false_type = bool_constant<false>;
bool_constant 的实参只能是 bool 类型, true_type 的 integral_constant::value
是true,false_type 的 value 是 false,构建 traits 的基础已经完成。
像 std::enable_if, is_same, remove_const, remove_reference 等这些是最常用的 traits,STL的代码中这些到处可见。
根据编译期布尔常量隐藏一个函数重载或模板特化。
// STRUCT TEMPLATE enable_if
template <bool _Test, class _Ty = void>
struct enable_if { // type is undefined for assumed !_Test
};
template <class _Ty> struct enable_if<true, _Ty> { // type is _Ty for _Test
using type = _Ty;
};
template <bool _Test, class _Ty = void>
using enable_if_t = typename enable_if<_Test, _Ty>::type;
若 B 为 _Test ,则 std::enable_if 拥有等同于 T 的公开成员 typedef type (第二个模板实参),否则,无该成员 typedef。
检测两个参数类型是否相同,如果相同特供 value 为 true,否则为false。实现简单,相同参数的继承 true_type, 不同参数的继承 false_type
// STRUCT TEMPLATE is_same
template <class _Ty1, class _Ty2>
struct is_same
: false_type { // determine whether _Ty1 and _Ty2 are the same type
};
template <class _Ty1>
struct is_same<_Ty1, _Ty1>
: true_type { // determine whether _Ty1 and _Ty2 are the same type
};
template <class _Ty, class _Uty>
constexpr bool is_same_v = is_same<_Ty, _Uty>::value;
控制给定类型限定符是否存在。volatile 同理。
// STRUCT TEMPLATE remove_const
template <class _Ty> struct remove_const { // remove top level const qualifier
using type = _Ty;
};
template <class _Ty>
struct remove_const<const _Ty> { // remove top level const qualifier
using type = _Ty;
};
template <class _Ty> using remove_const_t = typename remove_const<_Ty>::type;
从给定类型移除引用,add_*value_reference 实现类似。
// STRUCT TEMPLATE remove_reference
template <class _Ty> struct remove_reference { // remove reference
using type = _Ty;
};
template <class _Ty> struct remove_reference<_Ty &> { // remove reference
using type = _Ty;
};
template <class _Ty>
struct remove_reference<_Ty &&> { // remove rvalue reference
using type = _Ty;
};
template <class _Ty>
using remove_reference_t = typename remove_reference<_Ty>::type;
像上面这些都是可以通过库来实现的 traits,这种一般也比较简单的。其他的和类 枚举 虚函数 这些相关一般都要通过内建支持。
最先想到的就是 is_trivial
,这种要通过库来实现就不可能了:
// STRUCT TEMPLATE is_trivial
template <class _Ty>
struct is_trivial
: bool_constant<__is_trivial(_Ty)> { // determine whether _Ty is trivial
};
__is_trivial
就是编译器的外挂了,traits 的这种实现一直秉持着能够库实现,绝不编译器去做的原则。
标签:temp typedef failure code ref 运算 lse for template
原文地址:https://www.cnblogs.com/shuqin/p/12263178.html