Modifying member functions of built-in objects - c++

I'm sure this has been answered many times, but I don't know how to search for this. Is this polymorphism? Overloading?
Basically I want to take a vector, and modify its functions the way I want them or create new ones.
E.g: I want push_back() to insert an element and keep the vector in descending order. So the addition would be to swap() the element to its respective place. Or I would like to add a new function pop_front().
That being said, I need it as a member function, e.g:
vector<int> x;
x.pop_front();
not:
pop_front(x);
Is this ever done in practice? I know I can just use existing containers, like a priority queue for my example, but I'd rather make completely custom functions.

Basically, std::vector is not designed to be base class, inherit from it would be a bad idea in general. For example its dtor is not virtual.
It's better to use composition here. e.g.
template <typename T>
class MyVector {
private:
std::vector<T> v;
public:
void pop_front() {
// processing on v ...
}
};

Related

How can I create a vector with a maximum length?

I want to create a container that provides all of the same functionality as a std::vector but with the caveat that you cannot add anymore elements once the vector reaches a specified size.
My first thought was to inherit from std::vector and do something like
template <typename T, unsigned int max>
class MyVector : public std::vector<T> {
public:
// override push_back, insert, fill constructor, etc...
// For example:
virtual void push_back(const T& var) override {
if (this.size() < max) vec.push_back(var);
}
};
But then I learned that inheriting STL containers is bad.
Second thought was to create a wrapper class, i.e.
template <typename T, unsigned int max>
class MyVector {
private:
std::vector<T> vec;
public:
// Wrappers for every single std::vector function...
iterator begin() { return vec.begin(); }
const_iterator begin() const { return vec.begin(); }
//and on and on and on...etc.
};
But this smells bad to me. Seems very difficult to maintain.
Am I missing something obvious, should I try an alternative approach?
How can I create a vector with a maximum length?
You cannot do that with std::vector. You can however refrain from inserting any elements after you reach some limit. For example:
if (v.size() < 10) {
// OK, we can insert
}
I want to create a container that provides all of the same functionality as a std::vector but with the caveat that you cannot add anymore elements once the vector reaches a specified size.
That, you can do.
virtual void push_back(const T& var) override {
std::vector::push_back isn't virtual, so you may not override it.
Also, I recommend considering whether the push back should be silently ignored in the case max is reached.
But then I learned that inheriting STL containers is bad.
To be more specific, publicly inheriting them is a bit precarious.
Using private inheritance, you can use using to pick the members that you wish to delegate directly, and implement the differing members manually.
Seems very difficult to maintain.
The standard library doesn't change very often, and the vector class hasn't changed much so far, and changes have been quite simple, so "very difficult" is debatable - although subjective of course.
You could use meta-programming to make it maintainable. But that may be bit of an over-engineered approach.

Extending a type in C++

Sadly, UFCS did not make it into C++17 and that left me with a recurring problem:
Sometimes I want to give types extra functionality using the method call syntax (without writing global functions). That would especially come handy when dealing with monads.
I see two options: One is inheritance, and the other is encapsulation. Because you cannot safely inherit from STL containers, that leaves encapsulation. For example, I want to extend std::optional, so I write:
template <typename T>
struct myoption {
// Some functionality
private:
std::optional<T> impl;
};
My problem is that every time I want to do this, I basically have to write all the constructors (and needed methods that you can use with the original type, like push_back for vectors) the original type has. Even a simpler container, like optional has 9 constructors. When using inheritance, I can simply 'inherit' the methods and constructors of a super-class. Is there a way to make this easier using encapsulation?
I would implement it by using private inheritance:
#define MAKE_PUBLIC(method) using std::vector<T>::method
template <typename T>
struct My_vector : private std::vector<T> {
MAKE_PUBLIC(push_back);
MAKE_PUBLIC(pop_back);
};
int main() {
My_vector<int> v;
v.push_back(3);
std::vector<int>* vec = new My_vector<int>; // won't compile
}
This way, you can make sure that you cannot create objects with dynamic type of My_vector and reduce the effort to make inherited methods accessible by a mere macro (or using directive) instead of creating forward functions for each member function and overload.

Fixed size std::vector at runtime?

Performance is crucial in my application
I need something that works like std::experimental::dynarray, so an array which size is decided at runtime.
So I thought about using a wrapper class for std::vector, giving all its features, but without the possibility to call resize, reserve or push_back. In few words, all the methods to change its size (please remind me if I missed some of them).
So I started writing this class:
CCVector.hpp:
template <typename T>
class CCVector{
public:
CCVector(size_t size);
T &operator[](typename std::vector<T>::size_type idx);
private:
std::vector<T> v;
};
CCVector.cpp:
template<typename T>
CCVector<T>::CCVector(size_t size) : v(size){}
template<typename T>
T& CCVector<T>::operator[](typename std::vector<T>::size_type idx){
return v[idx];
}
But I this point I thought I have to re-implement every method of std::vector that I need! For example begin, end, size etc, and I don't know how to implement all of them...Besides, this is really bad for maintenance: as soon as I need a new method from std::vector I need to re-implement it in CCVector.
All of this because I want fixed size arrays at runtime. How can I solve this without using the non-standard std::experimental::dynarray?
Use private inheritance and then import the functions you want using the using declaration to introduce the names you want into your class.
template<class T>
class MyVector : private std::vector<T>
{
public:
using std::vector<T>::end;
// etc
};
(With private inheritance you don't get the issue with vector not having a virtual destructor which is the reason most people don't like inheriting from standard containers)
Privately inheriting std::vector is as proposed in the other answer is one approach.
There is some memory overhead for using resizable container where a non-resizable would suffice. std::vector is typically around ~4 x size of a data pointer. You can store a pointer to data + length in half of that:
template<class T>
class dynarray
{
std::unique_ptr<T[]> data;
T* end; // or size_t size
//TODO functions
};
The downside obviously is that you must re-implement all of the boilerplate, that you could otherwise inherit from std::vector. That said, all of the boilerplate is quite trivial - there is just lots of it.
You are right that std::vector has quite a few member functions that you need to expose to the outside, but there are not thaaat many. For example, see here http://www.cplusplus.com/reference/vector/vector/
Furthermore, you do not need to (and should not) reimplement std::vector on your own - relying on tested, fast code like your STL is almost always the better option.
So, instead of reimplementing, simply "forward" the functions to the outside, like so:
iterator begin()
{
return v.begin();
}
This is a bit of boilerplate code, but if you do this once for the non-resizing functions of std::vector, you are done.
Edit:
Also, do not inherit from std::vector. This is a bad idea for many reasons.
Okay, I was a bit quick here, sorry for that. As the comments, and this post suggest, inheriting from an STL container is not inherently bad. Particularly if you use private inheritance, it might just be a valid solution for the given task.

How to avoid unnecessary construction of std::vector<Base *>

I have two classes
class Base{ ... };
class Derived : public Base { ... };
and some other function which operates and modifies a collection of Base pointers:
void foo(std::vector<Base *> ptrs_to_base);
I have a std::vector<Derived> which holds my data. To pass it to foo I can construct a new vector of type std::vector<Base *> containing all pointers. In many situations this will be the easiest thing to do. However, I don't like the overhead with which it comes and in some situations it is simply not affordable to allocate dynamic memory.
Is there a way to change foo's interface as to do everything in place? In principle there should be no need for unnecessary construction of collections. I know there is no easy way, so usage of additional (multi-purpose) helper classes would be fine.
For example
template <typename Iter>
void foo(Iter begin, Iter end) {
//*begin is of type Base*
...
}
std::vector<Derived> elements;
std::vector<Derived *> ptrs_to_elements = ... // construct from elements
foo(ptrs_to_elements.begin(), ptrs_to_elements.end());
would be one solution which requires templates and doesn't make it obvious that only pointers of type Base * are required. Edit: W.F. gave a way to recognize wrong usages of this template. It still requires the unnecessary construction of ptrs_to_elements.
The problem is that your function takes a vector as parameter. And vector as any other standard container does not implement a simple interface and is not intended to be derived.
That means that if you only have a vector of objects and need a vector of pointers your only choice is to build a new vector.
For that reason, standard C++ container are very good to store objects, but public interface should rather use... interfaces of simple wrappers around them to make on flight transformation easier (if not simply just possible)

Vectors Classes Private/Public

In C++ is always better to keep data of a class as private members.
If a class has a vector as member is better to put it as a private or public member?
If I have a vector as private member I cannot easily access to the member function of the vector. So I have to design the class with a method for every function I need to access the vector methods?
Example given:
class MyClass{
private:
std::vector<int> _myints;
public:
get_SizeMyints(){return _myints.size();}
add_IntToMyints(int x){_myints.push_back(x));
};
or is better to keep the vector public and call MyClass._myints.push_back(x)?
---------------------edit--------------
and just for clarity for what is needed this question:
snake.h:
enum directions{UP, DOWN, RIGHT, LEFT, IN, OUT, FW, RW };
class Snake
{
private:
enum directions head_dir;
int cubes_taken;
float score;
struct_color snake_color;
V4 head_pos;
public:
std::vector<Polygon4> p_list; //the public vector which should be private...
Snake();
V4 get_head_pos();
Polygon4 create_cube(V4 point);
void initialize_snake();
void move(directions);
void set_head_dir(directions dir);
directions get_head_dir();
void sum_cubes_taken(int x);
int get_cube_taken();
void sum_score(float x);
float get_score();
void set_snake_color();
};
so now I know how to change the code.
btw... a question, if I need to copy the vector in an other class like this: GlBox.p_list = Snake.p_list (works if are private) what will be an efficent method if they where private?
Running a for cycle to copy the the elements and pusshing back them in the GLBox.p_list seems a bit inefficent to me (but may be just an impression) :(
If it doesn't matter if someone comes along and empties the vector or rearranges all it's elements, then make it public. If it matters, then yes, you should make it protected/private, and make public wrappers like you have. [Edit] Since you say "it's a snake", that means it'd be bad if someone came and removed or replaced bits. Ergo, you should make it protected or private. [/Edit]
You can simplify a lot of them:
MyClass {
private:
std::vector<int> _myints;
public:
const std::vector<int>& get_ints() const {return _myints;}
add_IntToMyints(int x){_myints.push_back(x));
};
That get_ints() function will allow someone to look at the vector all they want, but won't let them change anything. However, better practice is to encapsulate the vector entirely. This will allow you to replace the vector with a deque or list or something else later on. You can get the size with std::distance(myobj.ints_begin(), myobj.ints_end());
MyClass {
private:
std::vector<int> _myints;
public:
typedef std::vector<int>::const_iterator const_iterator;
const_iterator ints_begin() const {return _myints.begin();}
const_iterator ints_end() const {return _myints.end();}
add_IntToMyints(int x){_myints.push_back(x));
};
For good encapsulation, you should keep your vector private.
Your question is not very concrete, so here's an answer in the same spirit:
Generally, your classes should be designed to express a particular concept and functionality. They should not just hand through another member class. If you find yourself replicating all the interface functions of a member object, something is wrong.
Maybe sometimes you really just need a collection of other things. In that case, consider a plain old aggregate, or even a tuple. But if you're designing a proper class, make the interface meaningful to the task at hand, and hide the implementation. So the main question here is, why do you need to expose the vector itself? What is its role in the class? What does its emptiness signify in terms of the semantics of your class?
Find the appropriate idioms and ideas to design a minimal, modular interface for your class, and the question might just go away by itself.
(One more idea: If for example you have some range-based needs, consider exposing a template member function accepting a pair of iterators. That way you leverage the power of generic algorithms without depending on the choice of container.)
Normally, good coding practice is to keep your data members private or protected, and provide whatever public methods will be needed to access them. Not all the methods of (in this case) vector, just what will be useful for your application.
That depends on your class's purpose. If you're trying simply trying to wrap the vector and want to use it as a vector you could make an argument for making the vector public.
Generally speaking I would suggest making it private and providing an appropriate interface to manipulate the container. Additionally this lets you change the container under the hood if a different container would ever be more appropriate (as long as you don't tie your public interface to the container type).
Further as an aside, avoid names that begin with underscores as there are some such identifiers reserved for the implementation and it's safer to just avoid all of them rather than trying to remember the rules in all cases.
A point to realize is that making the std::vector private is only half of the story when it comes to good encapsulation. For example, if you have:
class MyClass {
public:
// Constructors, other member functions, etc.
int getIntAt(int index) const;
private:
std::vector<int> myInts_;
};
...then arguably, this is no better than just making myInts_ public. Either way, clients will write code using MyClass which is dependent on the fact that the underlying representation requires the use of a std::vector. This means that in the future, if you decide that a more efficient implementation would utilize a std::list instead:
class MyClass {
public:
// Constructors, other member functions, etc.
int getIntAt(int index) const; // whoops!
private:
std::list<int> myInts_;
};
...now you have a problem. Since you can't access into a std::list by index, you would either have to get rid of getIntAt, or implement getIntAt using a loop. Neither option is good; in the first case, you now have clients with code that doesn't compile. In the second case, you now have clients with code that just silently became less efficient.
This is the danger of exposing any public member functions which are specific to your choice of implementation. It's important to keep flexibility/future maintenance in mind when designing your class interface. There are a number of ways you could do this with your particular example; see Mooing Duck's answer for one such interface that exposes iterators.
Or, if you would like to maximize code readability, you could design the interface around what MyClass logically represents; in your case, a snake:
class MyClass {
public:
// Constructors, etc.
void addToHead(int value);
void addToTail(int value);
void removeFromHead();
void removeFromTail();
private:
// implementation details which the client shouldn't care about
};
This offers an abstraction of a snake object in your program, and the simplified interface gives you the flexibility to choose whatever implementation suits it best. And if the situation arises, you can always change that implementation without breaking client code.
Theoretically in Object Oriented Programming any attributes should be private and gain access to them via public methods such as Get() and Set().
I think you question is not complete, but what I understand from what you're trying to achieve you need to inherit from std::vector and extend its functionality, to both satisfy your fast access needs and not messing around with encapsulation. (Consider reading on "Inheritance" first from any C++ book, or other OO language)
Having said that, your code might look as following:
class MyClass : public std::vector<int>
{
//whatever else you need goes here
}
int main(void)
{
MyClass var;
var.push_back(3);
int size = var.size(); // size will be 1
}
Hope this answered your question