什么是std :: decay以及什么时候应该使用?

时间:2014-09-08 20:11:02

标签: c++ c++11 standard-library

std::decay存在的原因是什么? 在什么情况下std::decay有用?

2 个答案:

答案 0 :(得分:154)

<笑话>它显然用于将放射性std::atomic类型衰变为非放射性类型。< / joke>

N2609是提出std::decay的论文。该文件解释说:

  

简单地说,decay<T>::type是身份类型转换,除了   如果T是数组类型或对函数类型的引用。在那些   decay<T>::type产生指针或指向函数的指针的情况,   分别

激励性的例子是C ++ 03 std::make_pair

template <class T1, class T2> 
inline pair<T1,T2> make_pair(T1 x, T2 y)
{ 
    return pair<T1,T2>(x, y); 
}

通过值接受其参数以使字符串文字起作用:

std::pair<std::string, int> p = make_pair("foo", 0);

如果它通过引用接受了它的参数,那么T1将被推断为数组类型,然后构造pair<T1, T2>将是不正确的。

但显然这会导致严重的低效率。因此需要decay来应用在按值传递时发生的转换集,允许您通过引用获得获取参数的效率,但仍然可以获得代码所需的类型转换使用字符串文字,数组类型,函数类型等:

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

注意:这不是实际的C ++ 11 make_pair实现 - C ++ 11 make_pair也会展开std::reference_wrapper

答案 1 :(得分:49)

在处理带有模板类型参数的模板函数时,通常会有通用参数。通用参数几乎总是一种或另一种参考。他们也是const-volatile合格的。因此,大多数类型特征都不能像你期望的那样对它们起作用:

template<class T>
void func(T&& param) {
    if (std::is_same<T,int>::value) 
        std::cout << "param is an int\n";
    else 
        std::cout << "param is not an int\n";
}

int main() {
    int three = 3;
    func(three);  //prints "param is not an int"!!!!
}

http://coliru.stacked-crooked.com/a/24476e60bd906bed

此处的解决方案是使用std::decay

template<class T>
void func(T&& param) {
    if (std::is_same<typename std::decay<T>::type,int>::value) 
        std::cout << "param is an int\n";
    else 
        std::cout << "param is not an int\n";
}

http://coliru.stacked-crooked.com/a/8cbd0119a28a18bd