Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type Decaying - What It Is And Why Is It There?

Tags:

c++

types

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.

like image 390
the swine Avatar asked Sep 11 '14 08:09

the swine


People also ask

What is Type decay?

Type decay would be how an array can decay into a pointer (i.e. char[] into char* ). – JBL.

What is Type decay in C++?

C++ProgrammingServer Side Programming. The loss of type and dimensions of an array is known as array decay. It occurs when we pass the array into a function by pointer or value. First address is sent to the array which is a pointer. That is why, the size of array is not the original one.

Why do arrays decay into pointers?

From Code 1, whenever arrays are passed as the arguments to functions, they are always passed by using the 'Pass by reference' mechanism. Because of this, they will decay into pointers in the function parameters.


1 Answers

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.

like image 168
Angew is no longer proud of SO Avatar answered Sep 28 '22 06:09

Angew is no longer proud of SO