0

I'd like to implement my own method for the std::string in C++. Is there any way to do this and if so, how would I go about it? For example, I'd ideally like for something like this to compile:

#include <iostream>

// Some kind of thing that implements the method .lower() into std::string

int main(){
    std::string s = "Hello, World!";
    std::cout << s.lower() << std::endl;
}

// Expected output: hello world

Thanks!

Omyy
  • 13
  • 3
  • 5
    Not possible. You can't extend a class once it's defined. Create a free function. – HolyBlackCat Jul 23 '22 at 15:25
  • Oh, alright. I already had the free functions, just thought maybe there was a way to add them to the class. Thanks – Omyy Jul 23 '22 at 15:35
  • The way to add methods to a class is by derivation. C++ is not Python :) –  Jul 23 '22 at 15:35
  • Please read: https://en.cppreference.com/w/cpp/string/byte/tolower – A M Jul 23 '22 at 15:49
  • 3
    @YvesDaoust Most STL classes are not designed to be derived from so making a derived class string class is also not a good option. Free functions are the way to go. – Pepijn Kramer Jul 23 '22 at 15:55
  • 1
    Under the category of "C++ language abuse: do not do this in actual code" (doing this could be **life threatening**, in that your coworkers might kill you), you can mimic extension methods: https://stackoverflow.com/a/57081233/4641116 – Eljay Jul 23 '22 at 16:00
  • If you're ok with operator-like notation: https://stackoverflow.com/questions/8425077/can-i-create-a-new-operator-in-c-and-how/41780190#41780190 – lorro Jul 23 '22 at 16:31
  • @lorro That's just evil ;), overloading operators should not change their semantics. I think this falls into Eljay's category (where bad things happen to developers). Recite mantra : "I shall not use tricks" – Pepijn Kramer Jul 23 '22 at 16:42
  • @PepijnKramer: "Most STL classes are not designed to be derived from": isn't this an opinion ? And we are specifically speaking ot the string class. –  Jul 23 '22 at 16:54
  • @YvesDaoust No this is not an opinion (at least not for containers). But in general AFAIK most classes only have interface + behavior specified (+ contiguous memory specifications where needed). The rest is implementation details and can differ between STL implementations and should not be relied on. (But correct me if I'm wrong) – Pepijn Kramer Jul 23 '22 at 17:06
  • @PepijnKramer From a programmer's point of view, it's surely unnatural. But there are many cases when you 'interface' with human beings: physicists, mathematicians, etc., who have a well-defined 'language' (DSL) and can communicate their ideas much quicker if you mimic that language in the codes. This is similar to OP's request: we all know we could add a `to_lower(const std::string&)` (actually, there's an implementation already), but OP would like a specific _syntax_. – lorro Jul 23 '22 at 17:09
  • @lorro Sure, and I did get that :) But managing/having managed large teams of developers... there is a lot of value in just sticking to the basics and not to have developer specific solutions (or tricks). – Pepijn Kramer Jul 23 '22 at 17:16
  • Inheriting from string isn't too bad an idea if you do it correctly. Another option is the string_view to get string capabilities in your own string class. – Abel Jul 24 '22 at 01:33
  • @PepijnKramer: do you have a reference that justifies your claim ? –  Jul 24 '22 at 16:53
  • @YvesDaoust : One thing is that std::string destructor is not virtual (at least not in MSVC STL). I also found these topics : https://stackoverflow.com/questions/2034916/is-it-okay-to-inherit-implementation-from-stl-containers-rather-than-delegate, https://stackoverflow.com/questions/6006860/why-should-one-not-derive-from-c-std-string-class. (And yes in some cases you could probably get away with inheritance but I just don't) – Pepijn Kramer Jul 24 '22 at 17:09

1 Answers1

2

C++ does not have the concept of extensions like other languages do, so your options are limited. Realistically, your only options are:

  1. Create your own string class that is composed of a std::string and offers its own modifiers

  2. Inherit from std::string to provide your own functions. This really isn't a good idea from an OO-perspective, but it is technically an option.

  3. Write a utility function to do this for you. This is the ideal/idiomatic solution.

In the latter case, the common way of doing this would be with either a free-function (in a namespace), or a static function in a StringUtilities class. You can also modify the input string to save on unnecessary copies, if that's desirable, e.g.:

// Take 's' by mutable reference so it modifies s in place
// returns the same reference to allow chaining, e.g.
//
// to_lower(s).find(...)
auto to_lower(std::string& s) -> std::string& {
    /* to lower logic */
    return s;
}

// or, as a static function:

class StringUtilities {
    static auto to_lower(std::string& s) -> std::string& { /* same as above */ }
};
Human-Compiler
  • 11,022
  • 1
  • 32
  • 59
  • 1
    Instead of a class with static functions, you should use a namespace. Class has its own idiomatic usages. – digito_evo Jul 23 '22 at 16:00
  • 1
    @digito_evo That's an _opinion_; there is no "idiomatic" use for this. Notably, static classes prevent things like ADL, and also ensure that `using namespace` does not strip the utility-class name's context. Static classes can also be used as `friend` names easily, whereas namespaces cannot. There are benefits to classes that are simply impossible with namespaces; but I wouldn't say either case is "idiomatic" – Human-Compiler Jul 23 '22 at 21:03