Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

restrict qualifier on member functions (restrict this pointer)

Note: To clarify, the question is not about the use of the restrict keyword in general, but specifically about applying it to member functions as described here.

gcc allows you to use the __restrict__ (the GNU++ equivalent to C99's restrict) qualifier on a member function, effectively making this a restrict qualified pointer within the function's scope. Where is the beef?

Most member functions work on other members, accessing them via this, which is a T* const (and normally unaliased). For this to be possibly aliased, there would need to be a second pointer-to-type in use within the member function somehow, and it would have to come from somewhere.
That is a situation which is regularly the case with non-member functions, such as for example all binary operators or any other free function that takes at least two pointers or references of an identical, non-trivial type. However, these functions don't have a this, so they're not relevant.

The assignment operator, copy constructor, and unary comparison operators are examples of member functions where this could in principle be aliased (since another object is passed via reference). So it only really makes sense to assign a restrict qualifier to these -- it should already be obvious to the compiler that all other functions have the restrict property anyway (because there is never a second pointer-to-T).

Now, if for example you used restrict on operator= you should consequentially not check for self-assignment at all, because you're saying that this is not aliased within the scope of that function (and if that's true, no self-assignment can possibly happen).
Obviously, this is something that you cannot possibly know in advance, and it's something that doesn't make sense either.

So, what would be a case where one would actually want to give a member function a restrict qualifier and where it makes sense?

like image 962
Damon Avatar asked Jul 24 '11 17:07

Damon


People also ask

What is restrict qualified pointer?

In the C programming language, restrict is a keyword, introduced by the C99 standard, that can be used in pointer declarations. By adding this type qualifier, a programmer hints to the compiler that for the lifetime of the pointer, no other pointer will be used to access the object to which it points.

What does restrict mean C++?

restrict says that two pointers cannot point to overlapping memory regions. The most common usage is for function arguments. This restricts how the function can be called, but allows for more compile optimizations. If the caller does not follow the restrict contract, undefined behavior can occur.

How do you use restrict keywords?

When the restrict keyword is used with a pointer p, then it tells the compiler, that ptr is only way to access the object pointed by this. So compiler will not add any additional checks. If the programmer uses restrict keyword then violate the above condition, it will generate some un-defined behavior.

Does C++ have restrict keyword?

restrict is not supported by C++. It is a C only keyword.


2 Answers

Either I am missing something, or your question does not make sense. this is not that different from any other argument to a member function, so why are you surprised that GCC allows you to apply restrict to it?

Regarding applying it to an assignment operator, you rightly point out that it would obviate the need for an explicit self-assignment test. Then you say:

Obviously, this is something that you cannot possibly know in advance

But this is always true when you use restrict for anything. For example, somebody might decide to call memcpy with overlapping memory regions; you "cannot possibly know in advance" that they will not do so. But the restrict declaration for the arguments of memcpy means they have committed an error if they do. In exactly the same way, if you declare an assignment operator restrict, you have made it an error for someone to self-assign objects of that class. There is nothing mysterious or contradictory about this at all; it is just part of the semantics of restrict that it imposes certain constraints on the rest of your code.

I am also not sure why you find it so impossible for a member function to take a pointer (or reference) to another object of the same type. Trivial example:

class Point {
public:
    double distance(const Point &other) const;
};

This sort of thing crops up all the time.

So the real question is, why do you think this is so different from any other argument? Or if you prefer, how did I miss your point so completely?

like image 157
Nemo Avatar answered Sep 23 '22 22:09

Nemo


I belive what you guys are missing is that an argument to a member function could also alias parts or an object. Here's an example

struct some_class {
    int some_value;

    void compute_something(int& result) {
        result = 2*some_value;
        ...
        result -= some_value;
    }
}

One would probably expect that to compile to

*(this + offsetof(some_value)) -> register1
2*register1 -> register2
...
register2 - register1 -> result

That code, unfortunately, would be wrong if someone passes a reference to some_value for result. Thus, a compiler would actually need to generate to following

*(this + offsetof(some_value)) -> register1
2*register1 -> register2
register2 -> result

...
*(this + offsetof(some_value)) -> register1
result -> register2
register2 - register1 -> register2
register2 -> result

which is obviously way less efficient. Note that unless compute_something is inlines, the compiler has no way of knowing whether result may alias some_value or not, so it has to assume the worst case, no matter no smart or dumb it is. So there a definite and very real advantage to restrict, even if applied to the this pointer.

like image 38
Florian Pflug Avatar answered Sep 23 '22 22:09

Florian Pflug