通常从概念上讲,模板必须作为类型参数传递,编译器会抱怨,因为这不是合法的 c++ - 至少在 c++11 之前并包括在内(更新 II:除了参见最后一个非专用模板定义示例)
这些概念经常被使用并且应该有一个名字。如果不清楚我的意思,请参阅下面的代码示例。
我的第一个想法是这也可以称为传递不完整的类型,但这是不正确的。另一位用户还表示,他对此一无所知,并随意将其命名为模板参数的后期绑定。我认为他的术语很好地形象化了这个概念。
我的问题是你如何正确地调用这背后的成语或涉及的模板?
更新Kerrek 建议将成语模板命名为 rebinding 。此名称仅呈现少数 google 搜索结果。但是我认为这也是一个很好的名字,因为标准分配器将它们相关的包装内部类称为rebind。
在以下示例中,您可以配置数据库是否使用map
或hashmap
内部:
#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;
}
或类似地
#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;
}
更新二:令我尴尬的是,我不知道以下解决方案,它只是将模板作为参数传递给模板实例化。在这种特殊情况下,传递非类型是合法的。
#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;
}
当然,欢迎使用其他方式重新绑定或后期绑定模板参数的示例。