让gcc支持成员函数模板的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> ‘ struct Functor’ ../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>)了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架