函数模板的trick
函数模板的trick
让gcc支持成员函数模板的trick
罗朝辉 (http://www.cnblogs.com/kesalin/)

#ifndef __MEMFUNTEMPLATE_H__
#define __MEMFUNTEMPLATE_H__ #include <stdio.h> class Base {};
class Derived : public Base {}; struct Functor {
template <typename T> void function() {
printf(" Primary template....\n");
} template<>
void function<int>(){
printf(" Specialization for int....\n");
} template<> void function<Base *>() {
printf(" Specialization for Base *....\n");
}
}; class Tester {
public:
static void DoTest()
{
Functor functor;
functor.function<char>();
functor.function<int>();
functor.function<Base *>();
functor.function<Derived *>();
}
}; #endif // __MEMFUNTEMPLATE_H__

在 VS2010 中编译运行是没有问题的,但在 gcc 4.7.3下,编译都通不过:
../src/MemFunTemplate.h:21:14: error: <strong>explicit specialization in non-namespace scope</strong> ‘structFunctor’../src/MemFunTemplate.h:22:24: error: template-id ‘function<int>’ in declaration of primary template../src/MemFunTemplate.h:26:14: error: explicit specialization in non-namespace scope ‘struct Functor’../src/MemFunTemplate.h:26:38: error: template-id ‘function<Base*>’ in declaration of primary template../src/MemFunTemplate.h:26:21: error: ‘void Functor::function()’ cannot be overloaded../src/MemFunTemplate.h:22:10: error: with ‘void Functor::function()’../src/MemFunTemplate.cpp: In function ‘int main()’:../src/MemFunTemplate.cpp:17:2: error: ‘DoTest’ is not a member of ‘Functor’ |
为了达到近似成员函数模板特化的效果,可以利用成员函数主模板以及重载函数来实现:

/*
* MemFunTemplate.h
*
* Created on: Jul 12, 2013
* Author: http://blog.csdn.net/kesalin/
*/ #ifndef MEMFUNTEMPLATE_H_
#define MEMFUNTEMPLATE_H_ #include <stdio.h> template<typename T>
struct DummyIdentity {
typedef T type;
}; class Base {};
class Derived : public Base {}; struct Functor {
template <typename T> void function() {
function(DummyIdentity<T>());
} private: template <typename T>
void function(DummyIdentity<T>) {
printf(" Primary template DummyIdentity<T>....\n");
} void function(DummyIdentity<int>) {
printf(" overload function for DummyIdentity<int>....\n");
} void function(DummyIdentity<Base *>) {
printf(" overload function for DummyIdentity<Base *>....\n");
}
}; class Tester {
public:
static void DoTest()
{
Functor functor;
functor.function<char>();
functor.function<int>();
functor.function<Base *>();
functor.function<Derived *>();
}
}; #endif /* MEMFUNTEMPLATE_H_ */

调用 DoTest() 运行结果如下:
Primary template DummyIdentity<T>....
overload function for DummyIdentity<int>....
overload function for DummyIdentity<Base *>....
Primary template DummyIdentity<T>....
注意:
VS2010 版本的代码,模板形参为 T,在实例化不会进行隐式类型转换。即用 Derived * 当作实参调用的是主模板,而不是 Base * 特化版本
而在 gcc 下,模板形参虽然也为T,但影响重载决议的 function 参数为:DummyIdentity<T>,用不同的实际参数实例化该模板,得到的是一堆重载函数。因此用 Derived * 当作实参时,调用的函数自然就是实例化的 void function(DummyIdentity<T>)了。
函数模板的trick的更多相关文章
- 让gcc支持成员函数模板的trick
让gcc支持成员函数模板的trick 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循“署名-非商业用途-保持一致”创作公用协议 gcc 4.7.3 不支持成员 ...
- c++函数模板作为类的成员函数,编译报错LNK2019的解决方法
为了使某个类的成员函数能对不同的参数进行相同的处理,需要用到函数模板,即template<typename T> void Function(). 编译时报错LNK2019 解决方法: 1 ...
- C++STL - 函数模板
模板主要是为了泛型编程,做到与类型无关 模板有函数模板和类模板,本文主要整理的是函数模板 1.函数模板定义 template<typename 类型形参1,typename 类型形参2,...& ...
- 使用getopt_long来解析参数的小函数模板
getopt_long原型 #define no_argument 0 #define required_argument 1 #define optional_argument 2 struct o ...
- C++函数重载和函数模板
1.函数重载 这是小菜鸟写的一个例子. 函数重载应该注意以下几点: 1.1重载函数有类似的功能: 1.2只能以参数的类型(形参个数和类型)来重载函数, int max(int a,int b);flo ...
- 零值初始化&字符串常数作为函数模板参数
1.在定义一个局部变量时,并希望该局部变量的初始化一个值,可以显示调用其默认构造函数,使其值为0(bool类型默认值为false). template <typename T> void ...
- 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板
[源码下载] 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板 作者:webabcd 介绍不可或缺 Windows Native 之 C++ ...
- Effective C++ -----条款45:运用成员函数模板接受所有兼容类型
请使用member function templates(成员函数模板)生成”可接受所有兼容类型“的函数. 如果你声明member templates 用于“泛化copy构造”或“泛化assignme ...
- c++ 左值右值 函数模板
1.先看一段代码,这就是一种函数模板的用法,但是红色的部分如果把a写成a++或者写成一个常量比如1,都是编译不过的,因为如果是a++的话,实际上首先是取得a的 值0,而0作为一个常量没有地址.写成1也 ...
随机推荐
- MongoDB学习笔记<两>
继续有shell学问,他们继续研究的例子,下面的知识: --文档数据插入 --文档数据删除 --文档数据更新 如下面的详细信息: 1.插入文档 db.person.insert({"name ...
- sqlite学习笔记5:插入数据,查询数据和删除数据
曾闻:全部的编程都是已数据为中心,觉得很有道理. 所谓数据库数据库,没有数据叫什么数据库,接下来就看看怎样在表中插入数据. 一 插入数据 1 创建一张表 首先为了插入数据,须要先创建一张表: CREA ...
- UITableView的常用方法
一.UITableView的代理方法 #pragma mark 每一行的高度 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtI ...
- C++多线程分析
我们开始谈论的线程之前先看看这些线载波前-进程. 进程,它是一个正在执行的程序的实例.是一个程序在其自身的地址空间的一次执行活动.进程是资源申请.调度.和独立执行的基本单位.进程有两部分组成: 1.操 ...
- ArcGIS课程:表面数据转换成矢量数据
虽然TIN (TIN) 和 terrain 数据收集被认为是载体表面.但它们实际上包括基于其他信息元素.并且该信息是在图象点.线或多边形原始格这可能是更实用的公式.在 ArcGIS 在,你可以很容易的 ...
- avalon.js实现一个简易日历
使用MVVM框架avalon.js实现一个简易日历 最近在做公司内部的运营管理系统,因为与日历密切相关,同时无需触发条件直接显示在页面上,所以针对这样的功能场景,我就用avalon快速实现了一个简 ...
- Ruby on Rails (ROR)类书籍
Ruby on Rails (ROR)类书籍下载地址及其他(整理) Ruby on Rails 如此之热,忍不住也去看了看热闹,现在把一些相关的电子图书下载地址整理下,方便有兴趣的朋友. 2006-0 ...
- 数据类型 text 和 varchar 在 add 运算符中不兼容
原文:数据类型 text 和 varchar 在 add 运算符中不兼容 在SQL Server2005中,使用类似下面的Update语句: 1 UPDATE tb_SmsBlacklist SET ...
- SSMS2008插件开发(4)--自定义菜单
原文:SSMS2008插件开发(4)--自定义菜单 打开上次的项目MySSMSAddin中的Connect类,发现该类继于了两个接口:IDTExtensibility2和IDTCommandTarge ...
- 一些小bug
1.ie6-ie8中是不支持的,需要加上下面这句话: filter: progid:DXImageTransform.Microsoft.Alpha(opacity=70); 2.去除虚线框 a ...