我很惊讶类型衰减在SO或其他地方没有得到很好的解释,也许我没有使用正确的术语进行搜索,或者我可能没有正确理解整个事情.我的问题是:它是什么,它是如何(为什么)到达那里以及它的规则是什么?
如果你想知道我为什么问,下面是我的啜泣类型衰变故事(不是问题的主题):
我最近在努力学习一些简单的模板,我想做这样的事情:
template <class FunObj>
double DoStuff(FunObj fob) // note that this returns double, not FunObj, as e.g. std::for_each() does
{ /* ... */ }
struct MyFunObj {
mutable size_t num_invoked; // collect usage statistics
MyFunObj()
:num_invoked(0)
{}
bool operator ()(double some_arg) const
{
++ num_invoked;
return sin(some_arg) < .5;
}
};
Run Code Online (Sandbox Code Playgroud)
这很好,有一个期望函数对象的模板函数和一个函数对象.该函数被设计为不返回函数对象的状态(因为类似的函数经常这样做;它返回了一些复杂计算的结果),所以我认为我会把它专门用于对象的引用.但类型衰减阻碍了(或者至少是我对它的理解):
MyFunObj fob;
DoStuff(fob); // passed by value, usage statistics are lost (no surprise here)
MyFunObj &ref = fob;
DoStuff(ref); // MyFunObj& decays to MyFunObj, usage statistics are lost
DoStuff(static_cast<MyFunObj&>(fob)); // again, hampered by type decay
Run Code Online (Sandbox Code Playgroud)
我知道如何解决这个问题,所以请不要回复.我只对类型衰变感兴趣,这只是作为我的问题的动机/一个说明性的例子.如果你愿意,你可以发一些仇恨供我使用mutable.
Rei*_*ica 12
我真的不认为你的问题显示了类型衰减的例子.术语"衰减"通常用于指代标准的函数到指针,数组到指针和左值到右值的转换.您要点击的是模板参数推导的规则.
问题是模板参数推导是基于类型而不是基于值类别.ref您的示例中的类型是MyFunObj,并且它是该类型的左值(BTW,完全相同fob).由于扣除适用于种类,FunObj被推导为类型的ref,这的确是MyFunObj.
在C++ 11之前,没有办法推断出引用类型.C++ 11用"转发引用"改变了这一点.这些引入了一种特殊情况,其中将类型的左值传递U给声明为T&&(其中T是函数模板的模板参数)的函数参数,U&而不是使用它作为推导类型U.但这是一个特殊的规则,一个例外.通常,值类别在类型推导中不起作用.