9

Given these 2 functions that modify and return a string:

// modify the original string, and for convenience return a reference to it
std::string &modify( std::string &str )
{
    // ...do something here to modify the string...
    return str;
}

// make a copy of the string before modifying it
std::string modify( const std::string &str )
{
    std::string s( str );
    return modify( s ); // could this not call the "const" version again?
}

This code works for me using GCC g++, but I don't understand why/how. I'd be worried that 2nd function would call itself, leaving me with out-of-control recursion until the stack is exhausted. Is this guaranteed to work?

rrhartjr
  • 2,112
  • 2
  • 15
  • 21
Stéphane
  • 19,459
  • 24
  • 95
  • 136
  • This is tail recursion, most likely. I'm not sure the semantics of turning a const-ref call into a loop, so not posting an answer, but look up tail recursion and you'll find more info. – ssube May 01 '13 at 19:42
  • 2
    @peachykeen: No, it's not recursion at all. – Fred Larson May 01 '13 at 19:44
  • Consider choosing a title that focuses the question better - e.g. "What guarantees that the overloaded non-const method is invoked?" – user2246674 May 01 '13 at 19:48

3 Answers3

9

You have two overloaded functions:

std::string &modify( std::string &str )
std::string modify( const std::string &str )

What you're passing is a non const-qualified std::string. Therefore, the function that takes the non const-qualified argument is a better fit. If that didn't exist, the compiler could convert the non const-qualified string to a const-qualified string to make the call, but for function overloading a call that requires no conversion is a better fit than a call that requires a conversion.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
3
return modify( s ); // could this not call the "const" version again?

No. It is not recursion. It would invoke the other overload whose parameter is std::string &.

It is because the type of the expression s is std::string & which matches with the parameter type of the other overloaded function.

In order to recurse, the argument at call-site needs to convert into std::string const &. But in your case, this conversion is unnecessary as there exists an overload which doesn't require conversion.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
1

This isn't recursion, it's overloading. When you call the second function, the argument going into it is a constant string. Inside that function, you call the other function which takes a non-const string. What you're doing is stripping the const-ness of the string and a better way of doing that would be to use const_cast.

I'll just link to this other stackoverflow thread.

Community
  • 1
  • 1
Shaz
  • 1,376
  • 8
  • 18
  • I don't want to remove constness. That would result in a seemingly const string getting modified! – Stéphane May 01 '13 at 19:55
  • What you can do is assign the non-const string by doing something like: std::string &str2 = const_cast(str). str will remain constant but you'll be able to modify str2 all you want. – Shaz May 01 '13 at 20:04