Often conceptually a template must be passed as a type argument and the compiler complains because this is not legal c++ - at least until and including c++11 (Update II: except see last example of non specialized template definition)
These concepts are often used and should have a name. See the code examples below if it is not clear what I mean.
My first thought was that this may also be called passing an incomplete type but this is not correct. Another user also states that he has no word for it and freely names it late binding of template arguments. I think his terminology visualizes the concept well.
My question is how do you call the idiom behind this or the involved templates properly?
UPDATE Kerrek suggests naming the idiom template rebinding. This name renders only a few google results. However I think it is a very good name too because the standard allocators call their related wrapped internal classes rebind.
In the following example you could configure if your database uses map
or hashmap
internally:
#include <map>
struct map_wrapper
{
template<typename K, typename V>
using type = std::map<K,V>;
};
template<typename storage>
struct my_database
{
typename storage::template type<int, int> x;
typename storage::template type<int, double> y;
};
main ()
{
my_database<map_wrapper> db;
db.x[0] = 1;
db.y[0] = 2.0;
}
Or similarly
#include <map>
#include <boost/mpl/apply.hpp>
template <typename storage>
struct my_database
{
typename boost::mpl::apply<storage, int>::type x;
typename boost::mpl::apply<storage, double>::type y;
};
int main ()
{
my_database< std::map<int, boost::mpl::_1> > db;
db.x[0] = 1;
db.y[0] = 2.0;
}
Update II: To my embarrassment I did not know the following solution which is just passing a template as argument to a template instantiation. In this special case it is legal to pass a non-type.
#include <map>
#include <unordered_map>
template<template<typename...> class Storage>
struct my_database
{
Storage <long,char> x;
Storage <long,double> y;
};
int main ()
{
my_database< std::map > db1;
db1.x[0] = '1';
db1.y[0] = 2.2;
my_database< std::unordered_map > db2;
db2.x[0] = '1';
db2.y[0] = 2.2;
}
Examples of other ways to rebind or late bind template arguments are of course welcomed.