使用C++0x新特性为模板参数指定约束条件
2010-10-14 13:58
363 查看
在编写C++类模板时,有时希望模板参数满足某种要求,即约束条件,比如要求某个模板类型参数T必须派生于基类TBase。
在C#泛型中可以通过where关键字来指定约束条件,而C++模板则缺乏类似的约束机制。
C++0x中引入了一些新的特性,C++标准库也得到了改进和扩展,有两篇不错的参考文章:
比如,WTL中的模板,其中的一些模板参数必须从指定类继承(直接或间接继承),才能编译通过,如CApplicationT类:
这个模板类有个类型参数TMainWindow,实现代码中调用了这个类的一些成员函数,如Create(…),ShowWindow()等等。然而,这些成员函数实际上是CWindow类的成员函数。也就是说,TMainWindow类必须从CWindow类继承(直接或间接继承),才能在模板实例化时正确编译通过。
否则,如果TMainWindow不是CWindow的派生类,在编译如下代码时:
编译器会提示如下错误:
e:\coding\mywtllib\wtlapp.h(62): error C2039: 'ShowWindow' : is not a member of 'CTestWindow'
d:\cpp\wtl\wtlapp\win7shell\mainapp.cpp(6) : see declaration of 'CTestWindow'
这种编译错误不够直观,当碰到某些不太常见的成员函数时,特别是使用别人编写的模板代码,又缺少文档说明时,很难搞清楚TMainWindow应当满足什么条件才能编译通过。
幸好,我们现在可以利用C++0x的一些新特性来显式指定TMainWindow必须从CWindow类继承(直接或间接继承),方法为在CApplicationT模板实现代码中添加一段静态断言代码:
这样,当TMainWindow不满足条件时,编译器就会提示如下错误:
e:\coding\mywtllib\wtlapp.h(25): error C2338: TMainWindow needs to be CWindow based.
这样,错误原因就清晰多了。
使用std::is_base_of<>时,需要添加头文件”#include <type_traits>”
在C#泛型中可以通过where关键字来指定约束条件,而C++模板则缺乏类似的约束机制。
C++0x中引入了一些新的特性,C++标准库也得到了改进和扩展,有两篇不错的参考文章:
Explicating the new C++ standard (C++0x), and its implementation in VC10
Standard C++ Library changes in Visual C++ 2010
利用这些新特性,可以为模板参数指定一些约束。比如,WTL中的模板,其中的一些模板参数必须从指定类继承(直接或间接继承),才能编译通过,如CApplicationT类:
template<typename T, typename TMainWindow, bool bInitializeCom = false>
class CApplicationT :
public CAppModule
{
public:
//Call this method in the application's entry point[_tWinMain(...)]
int WinMain(HINSTANCE hInstance,LPTSTR lpCmdLine,int nCmdShow)
{
//Ensure that TMainWindow is derived from CWindow
static_assert(std::is_base_of<CWindow,TMainWindow>::value,
"TMainWindow needs to be CWindow based.");
UNREFERENCED_PARAMETER(lpCmdLine);
T* pT = static_cast<T*>(this);
//......
int nRet = 0;
{
CMessageLoop msgLoop;
AddMessageLoop(&msgLoop);
TMainWindow wndMain;
_g_hMainWindow = wndMain.Create(NULL,CWindow::rcDefault);
if(_g_hMainWindow == NULL)
{
ATLTRACE(_T("Failed to create Main window!\n"));
return 0;
}
wndMain.ShowWindow(nCmdShow);
wndMain.UpdateWindow();
wndMain.CenterWindow();
//......
这个模板类有个类型参数TMainWindow,实现代码中调用了这个类的一些成员函数,如Create(…),ShowWindow()等等。然而,这些成员函数实际上是CWindow类的成员函数。也就是说,TMainWindow类必须从CWindow类继承(直接或间接继承),才能在模板实例化时正确编译通过。
否则,如果TMainWindow不是CWindow的派生类,在编译如下代码时:
CApplication<CTestWindow> g_MainApp;
编译器会提示如下错误:
e:\coding\mywtllib\wtlapp.h(56): error C2039: 'Create' : is not a member of 'CTestWindow' d:\cpp\wtl\wtlapp\win7shell\mainapp.cpp(6) : see declaration of 'CTestWindow'
e:\coding\mywtllib\wtlapp.h(62): error C2039: 'ShowWindow' : is not a member of 'CTestWindow'
d:\cpp\wtl\wtlapp\win7shell\mainapp.cpp(6) : see declaration of 'CTestWindow'
这种编译错误不够直观,当碰到某些不太常见的成员函数时,特别是使用别人编写的模板代码,又缺少文档说明时,很难搞清楚TMainWindow应当满足什么条件才能编译通过。
幸好,我们现在可以利用C++0x的一些新特性来显式指定TMainWindow必须从CWindow类继承(直接或间接继承),方法为在CApplicationT模板实现代码中添加一段静态断言代码:
template<typename T, typename TMainWindow, bool bInitializeCom = false>
class CApplicationT :
public CAppModule
{
public:
//Call this method in the application's entry point[_tWinMain(...)]
int WinMain(HINSTANCE hInstance,LPTSTR lpCmdLine,int nCmdShow)
{
//Ensure that TMainWindow is derived from CWindow
static_assert(std::is_base_of<CWindow,TMainWindow>::value,
"TMainWindow needs to be CWindow based.");
UNREFERENCED_PARAMETER(lpCmdLine);
T* pT = static_cast<T*>(this);
//......
这样,当TMainWindow不满足条件时,编译器就会提示如下错误:
e:\coding\mywtllib\wtlapp.h(25): error C2338: TMainWindow needs to be CWindow based.
这样,错误原因就清晰多了。
使用std::is_base_of<>时,需要添加头文件”#include <type_traits>”
相关文章推荐
- c++模板特性---------可变参数的使用
- 泛型约束where条件的使用(通过类型参数动态反射创建实例)
- 泛型约束where条件的使用(可以通过类型参数动态反射创建实例)
- oracle EXP导出一张表时使用query参数指定where条件
- 使用信鸽推送时打开指定页面的同时获取相关参数
- Putty使用指定用户自动登录参数
- 使用命令参数方式指定log4j配置文件
- 使用gcc编译时,头文件和库的位置指定参数
- 根据参数指定的列名和值查询员工信息(使用动态sql语句)
- ECShop系统后台添加/修改分类时,指定分类所使用的模板文件!
- 让存储过程中的查询语句按照不同查询条件进行优化(即每次查询都使用参数option(recompile))
- 使用JS替换URL中的指定参数
- 使用JS替换URL中的指定参数
- 在应使用条件的上下文(在 'between@P1' 附近)中指定了非布尔类型的表达式。 ; unc
- Tableau--使用参数为报表增加一个统计周期筛选条件(日,周,月,季度,年)
- 如何指定输出参数,当您使用在 sp _ executesql SQL Server 中存储过程
- 在Cognos报表中使用钻取特性,参数传递
- 使用C++11变长参数模板 处理任意长度、类型之参数
- 一步步学习Reporting Services(二) 在报表中使用简单的参数作为查询条件
- ORA-02436: 日期或系统变量在 CHECK 约束条件中指定错误