C++ 什么是 std::decay 以及何时使用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25732386/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:25:10  来源:igfitidea点击:

What is std::decay and when it should be used?

c++c++11standard-library

提问by Eric Javier Hernandez Saura

What are the reasons for the existence of std::decay? In what situations is std::decayuseful?

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

回答by T.C.

<joke>It's obviously used to decay radioactive std::atomictypes into non-radioactive ones.</joke>

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

N2609is the paper that proposed std::decay. The paper explains:

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

Simply put, decay<T>::typeis the identity type-transformation except if T is an array type or a reference to a function type. In those cases the decay<T>::typeyields a pointer or a pointer to a function, respectively.

简单地说,decay<T>::type就是身份类型转换,除非 T 是数组类型或对函数类型的引用。在这些情况下,分别decay<T>::type产生一个指针或指向函数的指针。

The motivating example is C++03 std::make_pair:

激励示例是 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); 
}

which accepted its parameters by value to make string literals work:

它按值接受其参数以使字符串文字工作:

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

If it accepted its parameters by reference, then T1will be deduced as an array type, and then constructing a pair<T1, T2>will be ill-formed.

如果它通过引用接受其参数,T1则将被推导为数组类型,然后构造 apair<T1, T2>将是格式错误的。

But obviously this leads to significant inefficiencies. Hence the need for decay, to apply the set of transformations that occurs when pass-by-value occurs, allowing you to get the efficiency of taking the parameters by reference, but still get the type transformations needed for your code to work with string literals, array types, function types and the like:

但显然这会导致显着的低效率。因此需要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)); 
}

Note:this is not the actual C++11 make_pairimplementation - the C++11 make_pairalso unwraps std::reference_wrappers.

注意:这不是实际的 C++11make_pair实现 - C++11make_pair也解包std::reference_wrappers。

回答by Mooing Duck

When dealing with template functions that take parameters of a template type, you often have universal parameters. Universal parameters are almost always references of one sort or another. They're also const-volatile qualified. As such, most type traits don't work on them as you'd expect:

在处理采用模板类型参数的模板函数时,您通常会使用通用参数。通用参数几乎总是一种或另一种引用。它们也是 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

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

The solution here is to use std::decay:

这里的解决方案是使用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

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