Reputation: 439
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
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
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;
}
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