FrankHB
2022-01-30 04:43:33 +08:00
<typename T, typename = xxx> 单独没什么实际意思,就 typename 后的模板形式参数允许省略没用到的名称这个知识点。
大部分情况下,看到不懂的构造,前后的标识符都可以当作关键字。这里如果要搜,直接搜 enable_if 就可以(另外有 C++14 简写 enable_if_t );事实上 enable_if/enable_if_t 原则上就只有一种用法,就是通过 SFINAE 选择需要的 overload/specialization 。
这样也更容易给 enable_if 出现在其它地方的各种奇葩用法打预防针(随便抄几坨我实际写过的):
template<class _tRange, yimpl(typename... _tParams,
typename = enable_if_t<sizeof...(_tParams) == 0>)>
auto
begin(_tRange& c, yimpl(_tParams&&...)) -> decltype(c.begin())
{
return c.begin();
}
template<typename _tFrom, typename _tTo, typename _type = void>
using enable_if_convertible_t = enable_if_t<is_convertible<_tFrom, _tTo>::value, _type>;
template<typename _fCallable, typename _type, typename... _tParams>
auto
invoke_impl(_fCallable&& f, _type&& obj, _tParams&&... args)
-> enable_if_t<is_callable_case1<decay_t<_fCallable>, _type>::value,
decltype((yforward(obj).*f)(yforward(args)...))>
{
return yconstraint(f), (yforward(obj).*f)(yforward(args)...);
}
template<typename _type, enable_if_t<!is_floating_point<_type>::value, int> = 0>
inline bool
Do(const _type& x)
{
return x % _type(2) != _type(0);
}
template<typename _type>
struct is_string_like<_type, enable_if_t<
is_object<decay_t<decltype(std::declval<_type>()[0])>>::value>> : true_
{};
以上只是展示 enable_if 能出现在什么地方,省略了一些为什么需要这么写的上下文(比如其它 overload 和 primary template ),所有共通用法都是 SFINAE (虽然混了点 expression SFINAE )。当然高玩可能可以在缺失上下文的情况下大致上猜出为什么需要(不得不)这样写,并累积对 C++ 的仇恨值而加快升级。