I very often run into the problem that I want to implement a data structure, and would like to allow users to extend it with functional functionality; that is add functionality but not bytes to the data structure. An example could be extending std::vector with a sum method:
#include <iostream>
#include <vector>
// for the header file
template<>
int std::vector<int>::sum();
//for the object file
template<>
int std::vector<int>::sum() {
int s=0;
for(auto v = this->begin(); v!=this->end(); ++v) s+=*v;
return s;
}
int main() {
std::vector<int> numbers;
numbers.push_back(5);
numbers.push_back(2);
numbers.push_back(6);
numbers.push_back(9);
std::cout << numbers.sum() << std::endl;
return 0;
}
So this is illegal, since one may not add functions to a class like this. Obviously this is some design decision of c++(11). It can be circumvented in two ways, that is defining a
int sum(std::vector<int> &v) { ... }
This is how std::sort works, so I guess it is the way c++(11) is intended. I think this is to the best of my knowledge the best way to do it in c++. However, it does not allow me to access private properties of std::vector. Maybe I am evil by assuming access to private properties in a (sort-of) method is fair. However, often I want users of my classes to not access certain stuff, however would like to allow extenders of my to access them. For example I can imagine that std::sort can be optimized w.r.t. specific container implementation knowledge and access.
Another way is inheriting std::vector, but I find that plain unacceptable for these reasons:
- if two parties have extended the class with methods, which one would like to use, then one would need to convert from one child class to another. This is ludicrous, as one converts data to data without actually changing bytes, as both child classes (can) have exactly the same memory implementation and segmentation. Please also note that data conversion in general is boilerplate code, and boilerplate code should imho be considered evil.
- one is unnecessarily mixing functionality with data structures, for example, a class name sum_vector or mean_vector is completely.
As a short reminder, I am not looking for answers like "You cannot do that in c++", I already know that (Add a method to existing C++ class in other file). However, I would like to know if there is a good way to do functional class extensions. How should I manage accessing private fields? What would be reasons why it is unreasonable for me to want private field access; why can't I discriminate between extender and user access?
Note: one could say that an extender needs protected access and a user needs public access, however, like I said, that would be for the inheritance way of extending, and I dislike it strongly for the aforementioned reasons.