Suppose the C++ below. Before calling of a->method1() it has an
assert (a) to check if a is sane.
The call a->method2() has no such assertion; instead method2 itself
checks for a valid this by means of assert (this).
It that viable code re. the C++ specification?
Even if it's covered by the standard, it not good style of course, and it's error prone if the code ever changes, e.g. if the method is refactored to a virtual method. I am just curios about what the standard has to say, and whether g++ code words by design or just by accident.
The code below works as expected with g++, i.e. the assertion in
method2 triggers as intended, because just to call method2 no
this pointer is needed.
#include <iostream>
#include <cassert>
struct A
{
int a;
A (int a) : a(a) {}
void method1 ()
{
std::cout << a << std::endl;
}
void method2 ()
{
assert (this);
std::cout << a << std::endl;
}
};
void func1 (A *a)
{
assert (a);
a->method1();
}
void func2 (A *a)
{
a->method2();
}
int main ()
{
func1 (new A (1));
func2 (new A (2));
func2 (nullptr);
}
Output
1
2
Assertion failed: this, file main.cpp, line 16
Even if it's [permitted] by the standard
It isn't.
it not good style of course
Nope.
and it's error prone if the code ever changes, e.g. if the method is refactored to a virtual method.
I concede that a virtual member function is more likely to cause a "crash" here, but you already have undefined behaviour and that's not just a theoretical concern: you can expect things like the assertion or conditions to be elided, or other weird things to happen.
This pattern is a big no-no.
I am just curios about what the standard has to say
It says:
[expr.ref/2][..] For the second option (arrow) the first expression shall be a prvalue having pointer type. The expressionE1->E2is converted to the equivalent form(*(E1)).E2[..]
[expr.unary.op/1]The unary*operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points. [..]
Notice that it doesn't explicitly say "the object must exist", but by saying that the expression refers to the object, it implicitly tells us that there must be an object. This sort of "gap" falls directly into the definition of undefined behaviour, by design.
whether g++ code words by design or just by accident.
The last one.
Answering your question up front: "C++: Is "assert (this)" a viable pattern?" - No.
assert(this); is pointless. The C++ standard guarantees that the this pointer is never nullptr in valid programs.
If your program has undefined behaviour then all bets are, of course, off and this might be nullptr. But an assert is not the correct fix in that case, fixing the UB is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With