2

Recently, I asked this question where one of the answers says:

There's no such thing as "implicit this parameter" in the standard. The standard calls it an "implicit object parameter".

Then someone commented that:

There's no such thing as "implicit this parameter" in the standard." seems wrong. From expr.call#4: "If the function is a non-static member function, the this parameter of the function shall be initialized with a pointer to the object of the call, converted as if by an explicit type conversion."

Seeing the above comment i think that the answer is technically incorrect because the answer said that "There's no such thing as "implicit this parameter" in the standard." while the standard clearly talks about the this parameter.

So how to interpret this further (pun intended)? I mean, it seems that the standard makes a distinction between the non-static member function and a constructor in the context of this parameter. For example, the standard says that for a non-static member function, the this parameter of the function shall be initialized with a pointer to the object of the call converted as if by an explicit type conversion. But the standard doesn't say the same for constructors. So why does the standard makes this distinction? I mean why doesn't the standard says that constructors also have an this parameter that get initialized by the passed argument just like for non-static member functions. This again leads to the deeper question that if there is no this parameter in the constructor unlike non-static member function, then how are we able to use this inside the constructor. For example, we know that we can write this->p = 0 inside the constructor as well as inside a non-static member function, where p is a data member. But in case of non-static member function, this is a parameter of that particular member function so this->p makes sense. But in case of constructor this is not a parameter, so how are we able to use this->p inside the constructor.

Originally, by reading the answers here, I thought that the implicit this parameter is an implementation detail. But after reading expr.call#4 it seems that it is not an implementation detail.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • I can't tell what your question is. Is it the title or the bolded sentence? – Passer By Apr 17 '22 at 13:53
  • If you have to say "pun intended", it's probably not a very good pun :-) – paxdiablo Apr 17 '22 at 13:58
  • @paxdiablo I disagreee. `this` has 2 meaning in that sentence. Just to emphasis(so that if someone only got the pun but not the other meaning) on that, i wrote "pun intended". – Jason Apr 17 '22 at 14:00
  • @PasserBy I have added some more explanation(example in particular) to clarify my question(if not already). – Jason Apr 17 '22 at 14:02
  • @Anya, I believe that is the very *definition* of "pun", two different meanings. I'm pretty certain (because of my warped mind from years of doing cryptic crosswords) I would have gotten it even without the assist, but I digress :-) – paxdiablo Apr 17 '22 at 14:12

2 Answers2

1

If you think this is some sort of implicit parameter, type in this code:

#include <iostream>

struct SimpleThing {
    int xyzzy;
    SimpleThing(): xyzzy(42) {}
    void print(int plugh, const int twisty) {
        std::cout << xyzzy << '\n';
        std::cout << plugh << '\n';
        std::cout << twisty << '\n';
        xyzzy = 0;
        plugh = 0;
        twisty = 0;
        this = 0;
    }
};

int main() {
    SimpleThing thing;
    thing.print(7, 99);
}

Then examine the errors you get:

prog.cpp: In member function ‘void SimpleThing::print(int, int)’:
prog.cpp:12:16: error: assignment of read-only parameter ‘twisty’
   12 |         twisty = 0;
      |         ~~~~~~~^~~
prog.cpp:13:16: error: lvalue required as left operand of assignment
   13 |         this = 0;
      |                ^

Note that the first two assignments work because they are modifiable variables. The third fails because it is, of course, (non-modifiable) const.

The attempted assignment to this doesn't look like any sort of "can't write to some sort of variable" diagnostic because it actually isn't.

The this keyword is a special marker inside non-static member functions (and constructors/destructors) that is translated into the address of the object being worked upon. While it may be passed as a hidden parameter, that is very much an implementation detail with which the standard does not concern itself.

The controlling section in the C++20 standard is in [class.this]:

In the body of a non-static member function, the keyword this is a prvalue whose value is the address of the object for which the function is called.

Nowhere in there (the entire section) does it mention that this is some sort of hidden parameter to the call.


And, regarding your question on why there is a distinction between non-static member functions and constructors, I don't believe this distinction involves the existence of this in either case, it instead has to do with the qualification of the type of this. It's existence in a constructor is undeniable as [class.ctor] states:

During the construction of an object, if the value of the object or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor’s this pointer, the value of the object or subobject thus obtained is unspecified.

In other words, I see your quote:

If the function is a non-static member function, the this parameter of the function is initialized with a pointer to the object of the call, converted as if by an explicit type conversion.

as specifying only the qualification of this, something that the constructor doesn't need.

There is no discussion of cv-qualified conversion for constructors as there is for other member functions because you can't actually create a cv-qualified constructor. It would be rather useless if your constructor were not allowed to set any member variables, for example :-)

While constructors can be used to create cv-qualified objects, the constructor itself is not cv-qualified. This is covered at the end of [class.this]:

Constructors and destructors shall not be declared const, volatile or const volatile. [Note: However, these functions can be invoked to create and destroy objects with cv-qualified types - end note]

And further in [class.ctor]:

A constructor can be invoked for a const, volatile or const volatile object. Const and volatile semantics are not applied on an object under construction. They come into effect when the constructor for the most derived object ends.


To be honest, I think WG21 would be better off going through the next iteration and replacing things like "the this parameter of the function" with a phrase that does not mention parameters at all (such as "the this property".

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I had no question about *"why there is no cv qualified conversion for ctors like there is for member functions"*. My question was that *"why standard doesn't say that ctors have `this` parameter just as the standard says that non-static member functions have `this` parameter"*. So i think that section/part of your answer is not needed since i already know about it. – Jason Apr 17 '22 at 15:02
  • @Anya, I believe the distinction being made here here is not whether or not a non-static-member-function/constructor *has* a `this`, it's the qualified *type* of the `this`. The former gets a cv-qualified type, the constructor does not. There's no doubt that a constructor *has* a `this`, `[class.ctor]` states: "During the construction of an object, if the value of the object or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor’s this pointer, the value of the object or subobject thus obtained is unspecified". Will clarify. – paxdiablo Apr 17 '22 at 23:35
0

Here's a quotation from this Draft C++17 Standard (bolding for emphasis, and to answer the question, is mine):

10.3.3 The using declaration      [namespace.udecl]



16     For the purpose of forming a set of candidates during overload resolution, the functions that are introduced by a using-declaration into a derived class are treated as though they were members of the derived class. In particular, the implicit this parameter shall be treated as if it were a pointer to the derived class rather than to the base class. This has no effect on the type of the function, and in all other respects the function remains a member of the base class. Likewise, constructors that are introduced by a using-declaration are treated as though they were constructors of the derived class when looking up the constructors of the derived class …

However I should add that the cited paragraph doesn't seem to be present in this later Draft Standard. In fact, that (later) Standard seems to use the phrase, "implicit object parameter," in similar clauses.

So, maybe you should add a specific version tag to your question: or , as there appears to be a divergence in the use (or not) of the term.


Note that the above citation is the only occurrence of the phrase, "implicit this parameter" in that Draft Standard.


Also, note that both documents I have linked are only Draft versions of the respective Standards, and both come with this cautionary escape-clause:

Note: this is an early draft. It’s known to be incomplet and incorrekt, and it has lots of bad formatting.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • In my question i had given a [link](https://timsong-cpp.github.io/cppwp/n4659/expr.call#4). So my question is about that version of the standard. You can add the respective tag to my question by looking at [this](https://timsong-cpp.github.io/cppwp/n4659/expr.call#4) draft. It seems to me that the draft is of C++17 standard(by looking at the date on the first page of the draft). Also **there are 3 mentiones of the phrase `this` parameter in [this](https://timsong-cpp.github.io/cppwp/n4659/expr.call#4) draft.** – Jason Apr 17 '22 at 15:09
  • @Anya • I counted 3 occurrences of "this parameter" in n4659, and of those, 1 occurrence of "implicit this parameter". And 23 occurrences of "implicit object parameter". I didn't check n4861 or n4910, which may be relevant if someone tidied up the wording. The constructor's `this` **keyword** is a bit of an oddity when inheritance, multiple inheritance, and virtual inheritance is involved. – Eljay Apr 17 '22 at 15:24
  • @Eljay [n4860](https://isocpp.org/files/papers/N4860.pdf) has 2 occurences of the phrase `this` parameter. I also think that if the implicit `this` parameter is indeed an implementation detail, then the standard should clearly says so. I know that during overload resolution, "implicit object parameter" comes into play. But at 2 places the standard also used "this parameter" which seems to imply that non-static member functions does have an implicit this parameter and it is not just an implementation detail. – Jason Apr 17 '22 at 16:01
  • @Anya • It doesn't *seem to imply* that to me. But I'm not a language lawyer. – Eljay Apr 17 '22 at 16:43
  • @Eljay The statement *"If the function is a non-static member function, the `this` parameter of the function shall be initialized with a pointer to the object of the call, converted as if by an explicit type conversion."* clearly implies that non-static member function have a `this` parameter otherwise what is being initialized here? – Jason Apr 17 '22 at 17:10
  • @Anya • There is a section in the n4659 called "expr.prim.this" which explains what `this` is. Whether or not `this` is a parameter appears to me to be an implementation detail. I have worked with compilers where `this` (as an implementation detail) was relied upon by the C code that interoperated with the C++ code. I've also worked with compilers where `this` was not passed in as a parameter (like other parameter in the C ABI), but rather was held in a CPU register. Although perhaps that compiler was not compliant, if your conjecture is correct. – Eljay Apr 17 '22 at 19:37