【发布时间】:2013-11-13 08:31:58
【问题描述】:
通常从概念上讲,模板必须作为类型参数传递,编译器会抱怨,因为这不是合法的c++ - 至少在c++11(包括)之前(更新二:除了看最后一个非专用模板定义的例子)
这些概念经常被使用并且应该有一个名字。如果不清楚我的意思,请参阅下面的代码示例。
我的第一个想法是这也可以称为传递不完整的类型,但这是不正确的。另一位用户也表示他对此一无所知,并随意将其命名为late binding of template arguments。我认为他的术语很好地形象化了这个概念。
我的问题是你如何正确地调用这背后的成语或涉及的模板?
UPDATE Kerrek 建议将成语命名为template 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;
}
当然欢迎重新绑定或延迟绑定模板参数的其他方法示例。
【问题讨论】:
-
@Kerrek,我不确定网络礼仪,但如果我根据您的建议改进我的问题并因此使您的 cmets 无效,您是否欢迎?无论如何,我邀请任何人编辑和改进我的问题。
-
这很好。评论是短暂的,如果原始评论作者没有删除它们,您可以将它们标记为“过时”。如果您发表类似“@user:我已更新我的帖子”之类的评论,那么评论者通常会回来并删除他们过时的 cmets...
-
我将您的包装操作称为“模板重新绑定”。我想这是一个比较传统的术语,但不要指望它。
-
@KerrekSB,我已经更新了受您的 cmets 启发的问题,并将删除我的一条评论。
-
您的地图包装器有些迂回,除非您的应用程序确实需要成员模板
type。否则,您可以简单地为my_database使用模板模板参数:template <template <typename K, typename T, typename ...Args> class C> struct my_database { C<int, int> x; }。不过,即使这样也不如将地图的实际 type 参数作为模板参数传递,因为这样更灵活。
标签: c++ templates nomenclature