Is it possible to have a static member variable in my template class if the class user does not need to know about this?

I have a template container class, something like this toy code:

template <class ItemType> class MyVector { public: MyVector() : _numItems(0), _items(NULL) {/* empty */} /** Returns a reference to the first item in our array, * or a default-constructed item if the array is empty. */ const ItemType & GetFirstItemWithDefault() const { return (_numItems > 0) ? _items[0] : _defaultItem; } [other methods omitted because they aren't relevant] private: int _numItems; // how many valid items (_items) points to ItemType * _items; // demand-allocated const ItemType _defaultItem; }; 

This class is really convenient to use - any code can simply # include "MyVector.h" and then start declaring objects like MyVector and MyVector, etc., and all this is Just Works (tm) without any distortion around the required one.

However, one thing that bothers me is the presence of the _defaultItem member variable, which should only give GetFirstItemWithDefault () the ability to return a valid link when the container is empty. The objection is that if I declare N MyVector objects, this means that there will also be N copies of _defaultItem in RAM - even if they are all the same and read-only, and therefore in fact there should be only one of them The process is not alone on MyVector.

So, the obvious solution is to make _defaultItem static .... but AFAICT, which comes with a cost: if I do this, it is no longer possible for any old code snippet to just include โ€œMyVector.hโ€ and go. .. now the user must necessarily declare storage for this static variable in one of his .cpp files, which is (a) a pain in the butt, and (b) means that the user of the code has to be aware of the details of the internal implementation of the class. Since _defaultItem is a private member variable, the class user should not think about it or even realize that it exists, not to mention that it needs to declare a repository for it. (and what if two separate code snippets declare a repository for it, each of which does not know the other, does the same? Does this not lead to a duplicate symbol character error?)

So my question is: is there a way to tell C ++ to automatically provide one unique store (for each instance of MyVector) for this static member variable so that MyVector users are not aware of this? (Note that it should be automatic for all possible instances of MyVector <...>, and not just for a few common cases)

+7
source share
3 answers

If this is a template, the compiler will do the magic for you. Just put the static member in the header and the compiler will see that it is just created once.

 template <class ItemType> class MyVector { public: //... private: static const ItemType _defaultItem; }; template <class ItemType> const ItemType MyVector<ItemType>::_defaultItem; 
+3
source

Why not make this default element static local to the function?

 const ItemType & GetFirstItemWithDefault() const { static const ItemType _default; return (_numItems > 0) ? _items[0] : _default; } 

This may not be what you need if you want to check the default element again in some other function, but for this you can simply put it in a separate function (which may be the static itself):

 static const ItemType& GetDefault() const { static const ItemType _default; return _default; } 

And call this function when you need to access the default item.


However, I believe that having a default element is not very nice. std::vector also does not have it and does not need it. Just tell the user to check if the vector is empty and will be executed. One problem with hidden statics is that you do not know ItemType . It could be a class that eats a ton of resources, and you just made another example! Perhaps change your mind about the design of this class, and then go to std::vector . :)

+8
source

So, the obvious solution is to make _defaultItem static .... but AFAICT, which comes with a cost: if I do, it is no longer possible for any old piece of code just #include "MyArray.h" and go ... now the user has to declare storage for this static variable in one of his .cpp files, which: (a) pain

No. This fear is not a concern. In template you can (required) declare a static variable in the same file.

 template <class ItemType> class MyVector { const ItemType _defaultItem; }; template <class ItemType> const ItemType MyVector<ItemType>::_defaultItem; // ok (no multiple symbols) 

Also note that this static member will only be created when GetFirstItemWithDefault() called. Therefore, do not worry about excessive distribution.

The only thing to worry about is to provide a default constructor for all ItemType , since the static object will mainly rely on the default constructor (which you must already care about, I think), What is it.

+3
source

All Articles