Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a Single String Utility Function with Dual Behavior in C++

Tags:

c++

I'm developing a string utility class that provides various string manipulation functions. I want users to have two options when using these functions:

  • Create and return a new string with the manipulation applied
  • Update their existing string in-place

Currently, I have implemented this with function overloading:

struct String final {
    static std::string toUpperCase(const std::string& str) {
        std::string result = str;
        std::transform(result.begin(), result.end(), result.begin(), 
                       [](unsigned char c) { return std::toupper(c); });
        return result;
    }
    
    static void toUpperCase(std::string& str) {
        std::transform(str.begin(), str.end(), str.begin(), 
                       [](unsigned char c) { return std::toupper(c); });
    }
};

int main() {
std::string str {"helloworld"};
std::string test = String::toUpperCase(str);
String::toUpperCase(str);
}

My Question Is it possible to combine these two functions into a single function that can both:

-> Return a new uppercase string when needed
-> Modify a string in-place when desired

What would be the most elegant and idiomatic C++ approach for this? I've considered templates and optional parameters, but I'm not sure which approach would provide the cleanest API for users.

If combining these two functions into a single function isn't possible, I'm also interested in knowing how to eliminate the code(std::transform...) duplication between them.

Note: I'm aware that the this implementation I've shown wouldn't compile. I'm sharing it specifically to illustrate the approach I was considering and the challenges I'm facing with function overloading and template specialization.

like image 365
Qwe Qwe Avatar asked Aug 30 '26 14:08

Qwe Qwe


1 Answers

To remove the duplicate code the first one can simply call the second one after it creates the new string object. This is a very common idiom.

namespace String {
std::string& toUpperCase(std::string& str) {
    std::for_each(str.begin(), str.end(),
    [](char& c) { c = std::toupper(c); });
    return str;
}

std::string toUpperCase(const std::string& str) {
    std::string result = str;
    toUpperCase(result);
    return result;
}
}

Unless the class String has some members that aren't part of this question, it should be a namespace.

I also changed std::transform to std::for_each , and I changed the return type of your second version (my first).

like image 132
Pete Becker Avatar answered Sep 01 '26 03:09

Pete Becker