Collection hardening

This may not be used too often but is a perfectly valuable technique. We can put a block at compile time on a collection that prevents us from doing x and y to the collection.

Templatious StaticFactory class has two static methods:

  • prevent(
  • allow(

With prevent method we will receive a reference to our original collection and we can say for it to prevent certain actions, such as add/removing elements. Unlike virtual exposure, where we have to throw if we want to make some noise here noise will be at compile time, which is even better. Let's try an example:

std::vector<int> v;

auto h = SF::prevent<
    templatious::VCOL_ADD
>(v);

SA::add(h,7);
// compile time error - addition is disabled.

What happened there? We had a vector v, we wrap it via reference in a VCollectionImpl class which is set to prevent addition. Mutating the handle (if we're allowed to mutate it) will mutate the original vector via reference.

How do we know we prevented addition? The full signature of prevent method is:

    template <
        int bitmask,
        template <class> class StoragePolicy =
            templatious::util::DefaultStoragePolicy,
        class T
    >
    static auto prevent(T&& t)

Allowed values for the bitmask are:

// prevent addition to collection
templatious::VCOL_ADD

// prevent erase of elements in collection
templatious::VCOL_CLEAR

// prevent traversal of collection
templatious::VCOL_TRAVERSE

// prevent access of collection
templatious::VCOL_ACCESS

// prevent size info of collection
templatious::VCOL_SIZE

So, there are five things we can prevent on a collection (see documentation of this method for more info), they default to false, so, if we call this with 0 everything will be allowed. Since underneath everything is in templates compiler will optimize all the ceremony out to get performance as usual.

Also, there's allow function, which only allows what specified and prevents everything else.

std::vector<int> v;

auto h = SF::allow<
    templatious::VCOL_ADD |
    templatious::VCOL_SIZE
>(v);

// ok - only addition and size info allowed
SA::add(h,7);
int size = SA::size(h);

// compile time error - traversal is disabled.
SA::begin(h);

Above, we only allow to add to the collection and size info. Kinda weird, but we allow that. Full signature of allow is:

    template <
        int bitmask,
        template <class> class StoragePolicy =
            templatious::util::DefaultStoragePolicy,
        class T
    >
    static auto allow(T&& t)

Now, another programmer, which might deal with the code you wrote might try to interact with the handle in ways you unintended, he would get a compile time error, see that it was put there explicitly, see your name in git blame and ask you what's the deal. Much better than hunting bugs at runtime, eh?