Code Bye

关于模版模版参数

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);
	}
}

要点在代码注释中都写出来了。
解释下,模版模版参数或说模版参数是类模版类型,是对类模版实现编译期动态,
其特化形式是类模版而不是特化的模版类。但是类模版是不能实例化的,而我们又
需要实例化,所以需要将类模版的模版参数显式指定,也即做为外层模版的模版参数,
调用时显式传入。

解决方案

5

能解释下常量模板的概念么?第一次听说

20

说的完全不是一件事啊
首先明确一点
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);

参数名皆可省略

5

谢谢,学习了

10

switch要加break

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明关于模版模版参数