Dmitry Teslenko
Dmitry Teslenko

Reputation: 921

How to specialize function template for a container?

I have function template that implements storing POD into stream:

template<typename T>
void dumps(std::ostream &os, const T &t)
{
    os.write(reinterpret_cast<const char *>(&t), sizeof(t));
}

Is there a way to specialize this template for containers to store container size and then call general implementation for container items?

Upvotes: 0

Views: 489

Answers (2)

R Sahu
R Sahu

Reputation: 206737

This works for std::vector, std::set, and std::list. Haven't tested for any other container.

It also works for POD types. Tested with int and the following struct.

struct A
{
   int a;
   double b;
};

// Forward declaration of the wrapper function.
template<typename T>
void dumps(std::ostream &os, const T &t);

// Implementation for POD types
template<typename T>
void dumps(std::ostream &os, const T &t, std::true_type)
{
   os.write(reinterpret_cast<const char *>(&t), sizeof(t));
}

// Implementation for container types
template<typename T>
void dumps(std::ostream &os, const T &t, std::false_type)
{
   auto size = std::distance(t.begin(), t.end());
   os.write(reinterpret_cast<const char *>(&size), sizeof(size));
   for ( auto const& item : t)
   {
      dumps(os, item);
   }
}

// Implementation of the wrapper function.
template<typename T>
void dumps(std::ostream &os, const T &t)
{
   dumps(os, t, std::integral_constant<bool, std::is_pod<T>::value>());
}

Upvotes: 1

Peter
Peter

Reputation: 36637

You just need to specialise the template for each container type. For example, with a vector.

template<typename T>
void dumps(std::ostream &s, const typename std::vector<T> &t)
{
    auto size = t.size();
    s.write(<reinterpret_cast<const char *>(&size), sizeof(size);
    for (auto const &item : t)
       dumps(s, item);      // using your dumps() for POD types
}

or (before C++11)

template<typename T>
void dumps(std::ostream &s, const typename std::vector<T> &t)
{
    typename std::vector<T>::size_type size = t.size();
    s.write(<reinterpret_cast<const char *>(&size), sizeof(size);

    for (std::vector<T>::const_iterator item = t.begin(), end = t.end();
              i != end; ++i)
       dumps(s, *item);      // using your dumps() for POD types
}

Similarly, specialise for other container types. Then it will also work for containers of containers.

Aside: this does assume you won't instantiate your templates for non-POD types. It is probably worth enforcing that (although I'll leave it as an exercise).

Upvotes: -1

Related Questions