类型腐朽 - 它是什么以及它为什么存在?

时间:2014-09-11 08:49:44

标签: c++ types

我很惊讶类型衰减在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;
    }
};

这很好,有一个期望函数对象的模板函数和一个函数对象。该函数被设计为不返回函数对象的状态(正如类似函数经常做的那样;它返回了一些复杂计算的结果),所以我认为我会把它专门用于引用物体。但类型衰减阻碍了(或者至少是我对它的理解):

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

我知道如何解决这个问题,所以请不要回复。我只对这种类型的衰变感兴趣,这只是作为我的问题的动机/一个说明性的例子。如果你愿意,你可以发表一些讨厌我使用mutable

1 个答案:

答案 0 :(得分:10)

我真的不认为你的问题显示了类型衰减的例子。术语&#34;衰变&#34;通常用于指代标准的函数到指针,数组到指针和左值到右值的转换。您要点击的是模板参数推断的规则。

问题是模板参数推断基于类型,不是基于值类别。示例中ref的类型是{{1}并且它是该类型的左值(BTW,与MyFunObj完全相同)。由于演绎适用于类型,fob会推导到FunObj类型,这确实是ref

在C ++ 11之前,没有办法推断出引用类型。 C ++ 11用&#34;转发引用改变了这一点。&#34;这些引入了一种特殊情况,其中将类型MyFunObj的左值传递给声明为U的函数参数(其中T&&是函数模板的模板参数)使用T作为演绎的类型而不是U&。但这是一个特殊的规则,一个例外。通常,价值类别不会在类型扣除中发挥作用。