I was searching for an implementation of extension methods in c++ and came upon this comp.std.c++ discussion which mentions that polymorphic_map
can be used to associated methods with a class, but, the provided link seems to be dead. Does anyone know what that answer was referring to, or if there is another way to extend classes in a similar manner to extension methods (perhaps through some usage of mixins?).
I know the canonical C++ solution is to use free functions; this is more out of curiosity than anything else.
C# extension method is a static method of a static class, where the "this" modifier is applied to the first parameter. The type of the first parameter will be the type that is extended. Extension methods are only in scope when you explicitly import the namespace into your source code with a using directive.
What is extension method? Extension methods in C# are methods applied to some existing class and they look like regular instance methods. This way we can "extend" existing classes we cannot change. Perhaps the best example of extension methods are HtmlHelper extensions used in ASP.NET MVC.
Different languages approach development in different ways. In particular C# and Java have a strong point of view with respect to OO that leads to everything is an object mindset (C# is a little more lax here). In that approach, extension methods provide a simple way of extending an existing object or interface to add new features.
There are no extension methods in C++, nor are they needed. When developing C++, forget the everything is an object paradigm --which, by the way, is false even in Java/C# [*]. A different mindset is taken in C++, there are objects, and the objects have operations that are inherently part of the object, but there are also other operations that form part of the interface and need not be part of the class. A must read by Herb Sutter is What's In a Class?, where the author defends (and I agree) that you can easily extend any given class with simple free functions.
As a particular simple example, the standard templated class basic_ostream
has a few member methods to dump the contents of some primitive types, and then it is enhanced with (also templated) free functions that extend that functionality to other types by using the existing public interface. For example, std::cout << 1;
is implemented as a member function, while std::cout << "Hi";
is a free function implemented in terms of other more basic members.
Extensibility in C++ is achieved by means of free functions, not by ways of adding new methods to existing objects.
[*] Everything is not an object.
In a given domain will contain a set of actual objects that can be modeled and operations that can be applied to them, in some cases those operations will be part of the object, but in some other cases they will not. In particular you will find utility classes in the languages that claim that everything is an object and those utility classes are nothing but a layer trying to hide the fact that those methods don't belong to any particular object.
Even some operations that are implemented as member functions are not really operations on the object. Consider addition for a Complex
number class, how is sum
(or +
) more of an operation on the first argument than the second? Why a.sum(b);
or b.sum(a)
, should it not be sum( a, b )
?
Forcing the operations to be member methods actually produces weird effects --but we are just used to them: a.equals(b);
and b.equals(a);
might have completely different results even if the implementation of equals
is fully symmetric. (Consider what happens when either a
or b
is a null pointer)
Boost Range Library's approach use operator|().
r | filtered(p);
I can write trim for string as follows in the same way, too.
#include <string> namespace string_extension { struct trim_t { std::string operator()(const std::string& s) const { ... return s; } }; const trim_t trim = {}; std::string operator|(const std::string& s, trim_t f) { return f(s); } } // namespace string_extension int main() { const std::string s = " abc "; const std::string result = s | string_extension::trim; }
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