Say I have this method:
bool match( /* some optional parameter */ );
that will do some string pattern matching and I wanted to allow it to be given an optional parameter that will only be filled with an instance of a known type (Match
) when the method match()
returns true
, would such a thing be possible?
In PHP I would be allowed to do:
public function match( Match &$match = null ) {
if( someMatchingRoutineMatched() ) {
$match = new Match();
return true;
}
return false; // $match will stay null
}
And then call it like so:
// $test is some instance of the class that implements match()
// I don't have to declare $m up front, since it will be filled by reference
if( $test->match( $m ) ) {
// $m would be filled with an instance of Match
}
else {
// $m would be null
}
Is something similar possible in c++?
I have kind of gotten it to work with the following
bool match( Match*& match ) {
if( /* something matches */ ) {
match = new Match;
return true;
}
return false;
}
... and then calling it like so:
Match* m = nullptr; // I wish I wouldn't have to declare this upfront as a nullptr
if( test.match( m ) ) {
// a match occured, so m should no longer be a null pointer
// but let's just make sure
if( m != nullptr ) {
// do something useful with m and afterwards delete it
delete m;
}
}
... however, this all feels a bit cumbersome. Furthermore I don't seem to be allowed to make the parameter optional like:
bool match( Match*& match = nullptr );
... since, I believe, references are not a allowed to be null, correct?
I hope you can see what I am trying to achieve and that you could give some insight in how I could go about achieving my goal, if it's at all possible to begin with, that is.
invalid initialization of non-const reference of type 'Match*&' from an rvalue of type 'Match*'
Match*& match = nullptr
is not allowed because references-to-non-const cannot bind to temporaries and passing nullptr
here creates a temporary Match*
.
You could return the pointer instead of passing a reference-to-non-const:
Match* match() {
if( /* something matches */ ) {
return new Match;
}
return nullptr;
}
Now a nullptr
return value means no matches, and non-nullptr
means that a match was found:
if( Match* m = test.match() ) { // nullptr means false, non-nullptr means true
if( m != nullptr ) { // always true here
// do something useful with m and afterwards delete it
delete m;
}
}
Or you could use overloading as @DanMašek mentioned:
bool match() {
Match* m = nullptr;
bool result = match(m);
delete m; // deleting a nullptr is a no-op
return result;
}
Last but definitely not least, mandatory use-unique_ptr
-over-raw-owning-pointer, so you don't have to worry about delete
, and it's clear without reading the documentation of match
whether the returned pointer is owning or non-owning:
unique_ptr<Match> match() {
if( /* something matches */ ) {
return make_unique<Match>( /* constructor arguments */ );
}
return nullptr;
}
if( auto m = test.match() ) { // m deduced to be of type unique_ptr<Match>
if( m != nullptr ) { // always true here
// do something useful with m and afterwards delete it
// no need to delete explicitly
}
}
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