天天看点

folly学习(二):C++中如何实现一个declval

作者:数据分析的事儿

std::declval的功能:

std::declval只能用于没有实际求值的上下文中,也不能创建任何对象。 但std::declval能在不创建对象的情况下,达到创建了一个该类型对象的效果或者说可以假定创建出了一个该类型对象。

一般和decltype配合使用

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);
    }
           

在folly中也实现了一个FOLLY_DECLVAL(T),位于

folly/Utility.h           

代码分析

#define FOLLY_DECLVAL(...) static_cast<__VA_ARGS__ (*)() noexcept>(nullptr)()
           

上述代码主要分为两部分,

一部分是类型转化:

static_cast<__VA_ARGS__ (*)() noexcept>(nullptr)
           

将一个nullptr指针类型转化为一个带noexcept的函数指针,其中函数的返回值,就是我们需要求得的类型对象。

所以只要加一对括号,调用该函数,就能产生我们需要的类型对象了。

static_cast<__VA_ARGS__ (*)() noexcept>(nullptr)()
           

这个宏的作用类似于std::declval(),但是,可以有效减少,函数模板实例化带来的,编译时间开销。

和std::declval()不同的是:

这个宏产生一个“T”类型的值,而不是“T&&”。

也就是说,这个宏产生的是一个纯右值,而不是一个将亡值。