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提了一種用法這段Code能動,不過會多出複製物件的成本1
2
3
4
5template <class T1, class T2>
inline pair<T1,T2> make_pair(T1 x, T2 y)
{
return pair<T1,T2>(x, y);
}如果我們改用Refernece的傳法重寫的話1
std::pair<std::string, int> p = make_pair("foo", 0);
以上麵這個範例的話,T1會被推導成1
2
3
4
5template <class T1, class T2>
inline pair<T1,T2> make_pair(T1&& x, T2&& y)
{
return pair<T1,T2>(x, y);
}const char[4]
,而不是const char *
。因此我們需要Decay
正確的寫法類似這樣1
2
3
4
5
6
7
8template <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範例
為了decay推導出primitive type,將變化包裝起來不讓外界知道。1
2
3
4
5
6
7
8template<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);
}
std::result_of
看了Stackoverflow,覺得這東西可以完全用decltype去代。有興趣的話可以參考CppReference的用法。