0%

Type traits in C++11

std::decay

如名稱所說,將所獲取到的類型作退化的動作。
先移除類型T的Reference,得累類型U

  • 如果 is_array::value 為 treu,修改類型type為remove_extent::type *
  • 如果 is_function::value 為 true,修改類型type為add_pointer::type
  • 否則,修改類型type為remove_cv::type
    不過decay可以用來作些什麼?

    將參數以值的方式傳回

    N2609提了一種用法
    1
    2
    3
    4
    5
    template <class T1, class T2> 
    inline pair<T1,T2> make_pair(T1 x, T2 y)
    {
    return pair<T1,T2>(x, y);
    }
    這段Code能動,不過會多出複製物件的成本
    1
    std::pair<std::string, int> p = make_pair("foo", 0);
    如果我們改用Refernece的傳法重寫的話
    1
    2
    3
    4
    5
    template <class T1, class T2> 
    inline pair<T1,T2> make_pair(T1&& x, T2&& y)
    {
    return pair<T1,T2>(x, y);
    }
    以上麵這個範例的話,T1會被推導成const char[4],而不是const char *。因此我們需要Decay
    正確的寫法類似這樣
    1
    2
    3
    4
    5
    6
    7
    8
    template <class T1, class T2> 
    inline pair< typename decay<T1>::type, typename decay<T2>::type >
    make_pair(T1&& x, T2&& y)
    {
    return pair< typename decay<T1>::type,
    typename decay<T2>::type >(std::forward<T1>(x),
    std::forward<T2>(y));
    }

    之前的make_resource範例

    1
    2
    3
    4
    5
    6
    7
    8
    template<typename Creator, typename Destructor, typename... Arguments>
    auto make_resource(Creator c, Destructor d, Arguments&&... args)
    {
    auto r = c(std::forward<Arguments>(args)...);
    if (!r) { throw std::runtime_error{ "Unable to create resource" }; }
    typedef typename std::decay<decltype(*r)>::type ResourceType;
    return std::unique_ptr<ResourceType, void(*)(ResourceType*)>(r, d);
    }
    為了decay推導出primitive type,將變化包裝起來不讓外界知道。

std::result_of

看了Stackoverflow,覺得這東西可以完全用decltype去代。有興趣的話可以參考CppReference的用法。

std::enable_if

SFINAE