std::declval 元函数

declval用于非求值上下文中
declval 原形:

template<typename _Tp>
  auto declval() noexcept -> decltype(__declval<_Tp>(0))
  {
    static_assert(__declval_protector<_Tp>::__stop,
	    "declval() must not be used!");
    return __declval<_Tp>(0);
  }
.....
template<typename _Tp>
  struct __declval_protector
  {
    static const bool __stop = false;
  };
....
template<typename _Tp, typename _Up = _Tp&&>
  _Up
  //因为传的是0(int类型),所以可引用的类型始终决策出这个版本(编译时多态)
  __declval(int);//利用SFINAE 使编译器能决策出最适合的版本 

template<typename _Tp>//void等不可引用的类型始终决策出这个版本
  _Tp
  __declval(long);//利用SFINAE 使编译器能决策出最适合的版本
  • __declval只有声明,没有定义;所以说用于求值上下文中会在链接时报错
    所以上面用了静态断言以提供更友好的错误信息;
  • __declval_protector 延迟实例化时机 用于防止无条件编译错误
  • 而在非求值上下文中使用时,不会对函数体内的语句进行检查,即不会执行静态断言,据此约束了使用场景;
  • ! 利用了函数返回值的特性, 对于__declval你传什么类型就返回什么类型的"实体", 注意:这种实例化并不是真正的在内存上构造出对象, 它在编译期非求值上下文中,仅仅是用于构造合法的语句
  • 注意返回类型不能写decltype(auto),虽然那样编译器也能推导出类型为decltype(__declval<_Tp>(0)); 但也意味着编译器需要看到函数体, 将触发函数体内的静态断言

用法1:求函数返回类型:

void commonF(int,double,char){};

template<class F,class... Args>//F:可调用对象 类型; Args:F的参数类型
  using InvokeResultOfFunc =
  decltype(declval<F>()(declval<Args>()...));
  
int main(){
//不仅可以用于普通函数, 还可用于函数对象的求返回类型
   InvokeResultOfFunc<float (int), int> a{};//a为float类型
   InvokeResultOfFunc<decltype(commonF), int,double,char> *b{};
}
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值