I\'ve seen some examples of C++ using template template parameters (that is templates which take templates as parameters) to do policy-based class design. What other uses do
Actually, usecase for template template parameters is rather obvious. Once you learn that C++ stdlib has gaping hole of not defining stream output operators for standard container types, you would proceed to write something like:
template
static inline std::ostream& operator<<(std::ostream& out, std::list const& v)
{
out << '[';
if (!v.empty()) {
for (typename std::list::const_iterator i = v.begin(); ;) {
out << *i;
if (++i == v.end())
break;
out << ", ";
}
}
out << ']';
return out;
}
Then you'd figure out that code for vector is just the same, for forward_list is the same, actually, even for multitude of map types it's still just the same. Those template classes don't have anything in common except for meta-interface/protocol, and using template template parameter allows to capture the commonality in all of them. Before proceeding to write a template though, it's worth to check a reference to recall that sequence containers accept 2 template arguments - for value type and allocator. While allocator is defaulted, we still should account for its existence in our template operator<<:
template class Container, class V, class A>
std::ostream& operator<<(std::ostream& out, Container const& v)
...
Voila, that will work automagically for all present and future sequence containers adhering to the standard protocol. To add maps to the mix, it would take a peek at reference to note that they accept 4 template params, so we'd need another version of the operator<< above with 4-arg template template param. We'd also see that std:pair tries to be rendered with 2-arg operator<< for sequence types we defined previously, so we would provide a specialization just for std::pair.
Btw, with C+11 which allows variadic templates (and thus should allow variadic template template args), it would be possible to have single operator<< to rule them all. For example:
#include
#include
#include
#include
template class C, class... Args>
std::ostream& operator <<(std::ostream& os, const C& objs)
{
os << __PRETTY_FUNCTION__ << '\n';
for (auto const& obj : objs)
os << obj << ' ';
return os;
}
int main()
{
std::vector vf { 1.1, 2.2, 3.3, 4.4 };
std::cout << vf << '\n';
std::list lc { 'a', 'b', 'c', 'd' };
std::cout << lc << '\n';
std::deque di { 1, 2, 3, 4 };
std::cout << di << '\n';
return 0;
}
Output
std::ostream &operator<<(std::ostream &, const C &) [T = float, C = vector, Args = >]
1.1 2.2 3.3 4.4
std::ostream &operator<<(std::ostream &, const C &) [T = char, C = list, Args = >]
a b c d
std::ostream &operator<<(std::ostream &, const C &) [T = int, C = deque, Args = >]
1 2 3 4