Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类型衰变-它是什么,为什么存在?_C++_Types - Fatal编程技术网

C++ 类型衰变-它是什么,为什么存在?

C++ 类型衰变-它是什么,为什么存在?,c++,types,C++,Types,我很惊讶在SO或其他地方没有很好地解释类型衰退,可能我没有使用正确的术语进行搜索,或者可能我没有正确理解整个事情。我的问题是:它是什么,它是如何(为什么)到达那里的,它的规则是什么? 如果你想知道我为什么这么问,下面是我的哭泣式衰变故事(不是问题的主题): 我最近正在努力使用一些简单的模板,我想做如下事情: template <class FunObj> double DoStuff(FunObj fob) // note that this returns double, not

我很惊讶在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;
    }
};
模板
double DoStuff(FunObj fob)//注意,它返回的是double,而不是FunObj,例如std::for_each()所返回的
{ /* ... */ }
结构MyFunObj{
可变大小\u t num\u调用;//收集使用情况统计信息
MyFunObj()
:num_已调用(0)
{}
布尔运算符()(双参数)常量
{
++调用的num_;
返回sin(某些参数)<.5;
}
};
这很好,有一个模板函数需要一个函数对象,还有一个函数对象。该函数被设计为不返回函数对象的状态(类似的函数经常这样做;它返回的是一些复杂计算的结果),所以我想我会专门将其作为对象的引用。但是类型衰退会阻碍(或者至少这是我对它的理解):

MyFunObj离岸价;
多斯塔夫(离岸价);//按值传递时,使用率统计信息将丢失(这并不奇怪)
MyFunObj&ref=离岸价;
多斯塔夫(参考);//MyFunObj&衰减为MyFunObj,使用统计信息将丢失
DoStuff(静态铸造(fob));//又一次,受到类型衰退的阻碍

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

发表一些仇恨,我真的认为你的问题没有显示类型衰退的例子。术语“衰减”通常用于指标准函数到指针、数组到指针以及左值到右值的转换。您所遇到的是模板参数推断的规则

问题是模板参数推导是基于类型的,而不是基于值类别的。在您的示例中,
ref
的类型是
MyFunObj
,它是该类型的左值(顺便说一句,对于
fob
,完全相同)。由于演绎作用于类型,
FunObj
被演绎为
ref
的类型,这确实是
MyFunObj


在C++11之前,无法推断引用类型。C++11用“转发引用”改变了这一点。这引入了一种特殊情况,将类型为
U
的左值传递给声明为
T&
的函数参数(其中
T
是函数模板的模板参数),使用
U&
作为推导类型,而不是
U
。但这是一个特殊的规则,一个例外。通常情况下,值类别在类型推断中不起作用。

在我看来,您的案例似乎与类型衰退无关。。。它涉及到这样一个事实:将引用传递给按值获取其参数的函数不会神奇地将参数类型更改为按引用传递。类型衰减是指数组如何衰减为指针(即
char[]
char*
)。将其作为参数传递时,请使用
std::ref(fob)
。塔达@JBL我认为OP的问题是为什么
FunObj
在第二个和第三个实例化中不是引用类型(第一个有点容易理解)。@JBL:It's reference decay;模板参数推断为
MyFunObj
,即使函数参数类型(用于推断)为
MyFunObj&
@MikeSeymour哦,对了,仍然存在模板参数推断。错过了。谢谢。+1我怀疑这正是理解上的脱节之处。回答得好。好的,是的,这似乎是我的答案。正如我所说,我不确定我是否正确理解了它,谢谢你的解释@我知道你提到的葡萄酒你知道如何解决它,但这里有一种方法也可以作为思考的食粮:调用
DoStuff(fob)
。然后想一想在
DoStuff
中声明
FunObj
类型的变量意味着什么,如果引用通常是演绎过程的一部分,这将是多么直观。@Angew是的,这是可以理解的。但对我来说,这将是更为期望的行为-如果我用引用专门化它,那么
FunObj
就是一个引用,如果我在模板函数中声明它的一个实例,这是一个引用—比在IMO中默默删除引用更有意义。但我想,删除所有引用以及与我的情况相反的“意外行为”的来源会使常见代码陷入强制转换的困境:)。@此外,还存在“引用”还是“左值”的问题应该是模板参数中
&
的源。到目前为止,标准C++中还没有真正的区别。考虑对某些指针<代码> P<代码>传递<代码> *P<代码>。左值?对推荐人?不还是这样?如果
p
是一个智能指针怎么办;它们必须返回引用才能返回左值。对我来说就像一罐虫子。
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