关于模版模版参数

风之子赛拉飞尔 2016-05-26 10:44:40
http://bbs.csdn.net/topics/391819297?page=1#post-401187341

偶然看到这个帖子,对于其中的模版模版参数的写法有点疑惑,自己试了一下,
在VS2008 (VC9.0)中正确的写法如下。

namespace std
{
// 示例类模版1
template <typename _Ty1, typename _Ty2>
struct Test1
{
Test1() : data(0) {}
~Test1() {}

DWORD data;
};

// 示例类模版2
template <typename _Ty1, typename _Ty2>
struct Test2
{
Test2() : data(0) {}
~Test2() {}

DWORD data;
};

// 全局链表,用于缓存
list<Test1<DWORD, DWORD>> g_list_test1;
list<Test2<DWORD, DWORD>> g_list_test2;

// 用于创建一个新实例的方法,原本目的是用于标准库容器类
// 隐含的条件:类模版的不同的特化模版类的大小与模版参数无关
// (几个基本的标准库容器均符合此条件,除了vector<bool>对应于
// 一个偏特化的子类模版,需要特别注意一下)
void* _func(DWORD nType)
{
switch (nType)
{
case 1:
{
g_list_test1.push_back(Test1<DWORD, DWORD>());
return &g_list_test1.back();
}

case 2:
{
g_list_test2.push_back(Test2<DWORD, DWORD>());
return &g_list_test2.back();
}

default:
ASSERTF();
break;
}
return NULL;
}

// 因函数模版不支持偏特化,所以需要先声明类模版,
// 实现对DWORD nType的编译期动态
template <template<typename _Ty1, typename _Ty2> class _Container>
struct _ContainerType;

template <>
struct _ContainerType<Test1>
{
enum { type=1 };
};

template <>
struct _ContainerType<Test2>
{
enum { type=2 };
};

// 外包的模版函数
template <typename _Ty1, typename _Ty2, template<typename _Ty1, typename _Ty2> class _Container>
_Container<_Ty1, _Ty2>& func()
{
return *(_Container<_Ty1, _Ty2>*)_func(_ContainerType<_Container>::type);
}
}


要点在代码注释中都写出来了。

解释下,模版模版参数或者说模版参数是类模版类型,是对类模版实现编译期动态,
其特化形式是类模版而不是特化的模版类。但是类模版是不能实例化的,而我们又
需要实例化,所以需要将类模版的模版参数显式指定,也即做为外层模版的模版参数,
调用时显式传入。
...全文
254 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
引用 6 楼 yshuise 的回复:
switch要加break
呵呵,见笑见笑,其实纯属笔误
  • 打赏
  • 举报
回复
引用 3 楼 pengzhixi 的回复:
能解释下常量模板的概念么?第一次听说
就是模版参数不是类型,而是数值,如: template <int> func() {} 它的实例化 func<0>()、func<1>()、func<2>() 等是不同的函数。 注意既然是模版,它就是编译期指定的(所以只能是常量而不能是变量),而函数参数是运行期指定的。 常量模版一是用于特定的算法,以提高运行期效率;一是用于编译期动态分配。 参见楼主我的博客,开头一个例子就是常量模版 http://blog.csdn.net/windsonzhl/article/details/4380914
yshuise 2016-05-28
  • 打赏
  • 举报
回复
switch要加break
纹枰老妖 2016-05-28
  • 打赏
  • 举报
回复
谢谢,学习了 。
iyomumx 2016-05-27
  • 打赏
  • 举报
回复
说的完全不是一件事啊 首先明确一点
template <typename _Ty1, typename _Ty2, template<typename _Ty1, typename _Ty2> class _Container>
    _Container<typename, typename>& func();
这样的写法是语法错误,只不过 msvc 照 C 语言传统将没有出现的依赖名称默认为 int 了,才推导出返回类型为 _Container<int, int> 可以省略的是模板参数名——如果你不使用的话——像这样:
template <typename _Ty1, typename _Ty2, template<typename, typename> class _Container>
    _Container<_Ty1, _Ty2>& func()
这里的 template class _Container 只是个声明,因此其参数名可以省略,就像前置模板声明
template <typename> class X;
或者前置函数声明
void func(int, double);
参数名皆可省略
pengzhixi 2016-05-27
  • 打赏
  • 举报
回复
能解释下常量模板的概念么?第一次听说
  • 打赏
  • 举报
回复
关于typename后省略类型名,经实验,如果如下形式,_Container<typename, typename> 会被编译器识别为_Container<int, int>,变成了常量模版,而不是我们想要的类型模版

template <template<typename _Ty1, typename _Ty2> class _Container>
    _Container<typename, typename>& func();
所以在如底楼的函数模版定义里,建议还是不要省略,以免出问题。
paschen 版主 2016-05-26
  • 打赏
  • 举报
回复
谢谢楼主分享,不过建议发表到博客

64,688

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧