函数模板的trick

让gcc支持成员函数模板的trick

罗朝辉 (http://www.cnblogs.com/kesalin/)

本文遵循“署名-非商业用途-保持一致”创作公用协议
 
gcc 4.7.3 不支持成员函数模板特化。如下代码:
 
#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>)了。

 
 
 
分类: C/C++
标签: C++gcctemplate

函数模板的trick的更多相关文章

  1. 让gcc支持成员函数模板的trick

    让gcc支持成员函数模板的trick 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循“署名-非商业用途-保持一致”创作公用协议   gcc 4.7.3 不支持成员 ...

  2. c++函数模板作为类的成员函数,编译报错LNK2019的解决方法

    为了使某个类的成员函数能对不同的参数进行相同的处理,需要用到函数模板,即template<typename T> void Function(). 编译时报错LNK2019 解决方法: 1 ...

  3. C++STL - 函数模板

    模板主要是为了泛型编程,做到与类型无关 模板有函数模板和类模板,本文主要整理的是函数模板 1.函数模板定义 template<typename 类型形参1,typename 类型形参2,...& ...

  4. 使用getopt_long来解析参数的小函数模板

    getopt_long原型 #define no_argument 0 #define required_argument 1 #define optional_argument 2 struct o ...

  5. C++函数重载和函数模板

    1.函数重载 这是小菜鸟写的一个例子. 函数重载应该注意以下几点: 1.1重载函数有类似的功能: 1.2只能以参数的类型(形参个数和类型)来重载函数, int max(int a,int b);flo ...

  6. 零值初始化&字符串常数作为函数模板参数

    1.在定义一个局部变量时,并希望该局部变量的初始化一个值,可以显示调用其默认构造函数,使其值为0(bool类型默认值为false). template <typename T> void ...

  7. 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板

    [源码下载] 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板 作者:webabcd 介绍不可或缺 Windows Native 之 C++ ...

  8. Effective C++ -----条款45:运用成员函数模板接受所有兼容类型

    请使用member function templates(成员函数模板)生成”可接受所有兼容类型“的函数. 如果你声明member templates 用于“泛化copy构造”或“泛化assignme ...

  9. c++ 左值右值 函数模板

    1.先看一段代码,这就是一种函数模板的用法,但是红色的部分如果把a写成a++或者写成一个常量比如1,都是编译不过的,因为如果是a++的话,实际上首先是取得a的 值0,而0作为一个常量没有地址.写成1也 ...

随机推荐

  1. 我在Github上的flare-spark项目

    Flare-Spark 介绍 我在自己的github上建了个flare-spark项目,本身是Apache Spark项目Master分支的镜像.在Spark的基础上,添加了flare子项目. 估计大 ...

  2. AlphaBlend參数BLENDFUNCTION

    AlphaBlend是Window自带的GDI函数,在作GUI的时候为了达到更美丽的效果我们经常常使用它. BLENDFUNCTION是AlphaBlend用控制透明效果的重要參数. 定义例如以下: ...

  3. c语言中实现从0-1的随机数输出

    原文:c语言中实现从0-1的随机数输出 今天晚上同学问了一个巨简单的问题,问我怎么用c语言输出0-1的随机数,可别说,一时之间还想不出来.在写的过程中发现,直接调用random函数还不能实现,用以下方 ...

  4. C语言库函数大全及应用实例一

    原文:C语言库函数大全及应用实例一                                 [编程资料]C语言库函数大全及应用实例一 函数名: abort 功 能: 异常终止一个进程 用 法: ...

  5. Android接口测试-JUnit入门

    1.下载:http://www.junit.org 2.配置AndroidManifest.xml,在application节点加入 <!--使用单元测试库-->        <u ...

  6. 《Shell十三问》笔记(上)

    <shell十三问>是网中人前辈首发在CU论坛上对SHELL的一些整理,非常值得一读 注:笔记的标号非问题标号,而是知识点的标号.本篇笔记记录的是1-10问的知识点 (1)IFS:Shel ...

  7. openwrt路由器更换了Flash之后需要修改的源码

    假如我使用的是WR703N,改为8M内存: 1 修改openwrt/target/linux/ar71xx/image/Makefile文件 $(eval $(call SingleProfile,T ...

  8. SQLCMD的介绍

    原文:SQLCMD的介绍 sqlcmd -S SERVERNAME -U USERNAME -P PASSWORD -i filename.sql 下面的内容是详细介绍sqlcmd的,有兴趣的朋友可以 ...

  9. 读书笔记—CLR via C#章节11-13

    前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可 ...

  10. 【转】Android学习之AndroidManifest.xml清单之<uses-feature>

    无意之中看了几个小时的官方英文文档,关于<uses-feature>的介绍.有必要在这里记录一下,应该有很多人不知道<uses-feature>到底是做什么用的,因为我们平时根 ...