类型衰减 - 它是什么以及它为什么存在? [英] Type Decaying - What It Is And Why Is It There?

查看:23
本文介绍了类型衰减 - 它是什么以及它为什么存在?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很惊讶在 SO 或其他地方没有很好地解释类型衰减,也许我没有使用正确的术语进行搜索,或者我没有正确理解整个事情.我的问题是:它是什么,它是如何(为什么)到达那里的,它的规则是什么?

<小时>

如果你想知道我为什么要问,下面是我的哭泣类型衰变故事(不过不是问题的主题):

我最近在一些简单的模板上苦苦挣扎,我想做这样的事情:

template double DoStuff(FunObj fob)//请注意,这将返回 double,而不是 FunObj,例如std::for_each() 确实{/* ... */}struct MyFunObj {可变 size_t num_invoked;//收集使用统计MyFunObj():num_invoked(0){}bool operator ()(double some_arg) const{++ num_invoked;返回罪(some_arg)<.5;}};

这一切都很好,有一个模板函数需要一个函数对象,还有一个函数对象.该函数被设计为不返回函数对象的状态(就像类似的函数经常做的那样;它返回的是一些复杂计算的结果),所以我想我会将它专门用于 引用物体.但是类型衰减妨碍了(或者至少这是我对它的理解):

MyFunObj fob;DoStuff(离岸价);//按值传递,使用统计丢失(这里不奇怪)MyFunObj &ref = fob;DoStuff(ref);//MyFunObj&衰减到 MyFunObj,使用统计数据丢失DoStuff(static_cast<MyFunObj>(fob));//再次受到类型衰减的阻碍

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

解决方案

我真的不认为您的问题显示了类型衰减的示例.术语衰减"通常用于指代标准函数到指针、数组到指针和左值到右值的转换.您所遇到的是模板参数推导的规则.

问题是模板参数推导基于类型,而不是值类别.在你的例子中ref的类型是MyFunObj,它是该类型的 lvalue(顺便说一句,对于 fob 完全相同).由于推导适用于类型,FunObj 被推导为 reftype,也就是 MyFunObj.

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

I was surprised the type decay is not explained very well on SO or elsewhere, maybe I did not search using the correct terms or maybe I'm not understanding the whole thing correctly. My question is: what it is, how (why) did it get there and what are the rules of it?


If you are wondering why I'm asking, below is my sob type decay story (not the subject of the question, though):

I was recently struggling with some simple templates and I wanted to do something like this:

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

This is all nice, there is a template function expecting a function object, and a function object. The function was designed to not return the state of the function object (as similar functions often do; it was returning a result of some intricate computation instead), so I thought I would specialize it for a reference to the object. But the type decay gets in the way (or at least that is my understanding of it):

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

I know how to solve this, so please do not reply how. I'm only interested in type decay as such and this is here only as a motivation of my question / an illustrative example. If you like, you can post some hate for my use of mutable.

解决方案

I don't really think your question shows an example of type decay. The term "decay" is commonly used to refer to the standard function-to-pointer, array-to-pointer and lvalue-to-rvalue conversions. What you're hitting are the rules for template argument deduction.

The thing is that template argument deduction is based on types, not on value categories. The type of ref in your example is MyFunObj, and it's an lvalue of that type (BTW, exactly the same holds for fob). Since deduction works on types, FunObj is deduced to the type of ref, which is indeed MyFunObj.

Before C++11, there was no way to deduce a reference type. C++11 changed this with "forwarding references." These have introduced a special case where passing an lvalue of type U to a function parameter declared as T&& (where T is a template parameter of the function template) uses U& as the type for deduction instead of U. But that's a special rule, an exception. Normally, value categories don't play a role in type deduction.

这篇关于类型衰减 - 它是什么以及它为什么存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆