Templated Map/Dictionary Implementation

This is somewhat similar to a previous question of mine, I'm trying to implement a templated Map class.

template<typename T, size_t M> class Array { ... } // Fixed-size container
template<typename T> class Vector { ... } // Variable-size container

Method 1:

template<typename KeyContainer, typename ValueContainer> class Map
{
    KeyContainer keys;
    ValueContainer values;
}

The problem here is I cannot guarantee that both containers will be the same, the user may pass an Array<T, M> as the key container and a Vector<T> as the value container leading to problems once the Map starts to exceed the size specified in the Array<T, M> template.

Method 2:

template<typename KeyType, typename ValueType, template<typename> class Container> class Map
{
    Container<KeyType> keys;
    Container<ValueType> values;
    // What if Container is an Array<T, M>?
}

but as demonstrated in my previous question that I linked it seems it is impossible to do so: receive a container template that has varying parameter count, unless there's some clever template tricks I'm not aware of.

Method 3:

Implement Method 1 and just put a note in the documentation that tells the user that KeyContainer and ValueContainer must be the same type of container.

Question: What would be the most optimal way to go about this problem?

Upvotes: 0

Views: 1302

Answers (2)

m8mble
m8mble

Reputation: 1545

You could store data as:

template <class Key, class Value, template<typename> class Container>
class Map
{
    Container<std::pair<Key, Value> > store;
};

Disclaimer: Personally I don't think this makes much sense. I don't see a use case for changing the Container used in a Map ever. It is also very hard for any user of your Map to see all requirement for a Container (eg. what methods does a Container need? Which may throw? Which are const?) In any reasonable scenario, users will use some default Container of yours. In any case the additional template argument won't see much use which is why I'd stick to a specific Container type.

Upvotes: 1

Vittorio Romeo
Vittorio Romeo

Reputation: 93264

Method 2 is a good solution, as you users can always "bind" template parameters by using template aliases:

template <typename T>
using ArrayOf5 = Array<T, 5>;

int main()
{
    Map<int, float, ArrayOf5> m;
}

live wandbox example


You could allow Container to take more template parameters by using a variadic pack:

template <typename...> class Container

But then it wouldn't work for non-type template parameters as in the case of Array.

Upvotes: 1

Related Questions