一道模板元编程题源码解答(replace_type)
今天有一同学在群上聊到一个比较好玩的题目(本人看书不多,后面才知是《C++模板元编程》第二章里面的一道习题), 我也抱着试一试的态度去完成它, 这道题也体现了c++模板元编程的基础和精髓: 类型就是数据。
题目如下所述:
Write a ternary metafunction replace_type<c,x,y> that takes an arbitrary compound type c as its first parameter, and replaces all occurrences of a type x within c with y:
typedef replace_type< void*, void, int >::type t1; // int*
typedef replace_type<
int const*[]
, int const
, long
>::type t2; // long* [10] typedef replace_type<
char& (*)(char&)
, char&
, long&
>::type t3; // long& (*)(long&)
下面第一部分是我的实现, 第二部分是测试代码:
1. 实现
namespace xusd{
template <typename C, typename X, typename Y>
struct replace_type;
template <typename X, typename Y>
struct replace_type<X, X, Y>{
typedef Y type;
};
template <typename C, typename X, typename Y>
struct replace_type_impl{
typedef C type;
};
template <typename C, typename X, typename Y>
struct replace_type:public replace_type_impl<C, X, Y>{ };
template <typename C, typename X, typename Y>
struct replace_type_impl<C const, X, Y>{
typedef typename replace_type<C, X, Y>::type const type;
};
template <typename C, typename X, typename Y>
struct replace_type_impl<C volatile, X, Y>{
typedef typename replace_type<C, X, Y>::type volatile type;
};
template <typename C, typename X, typename Y>
struct replace_type_impl<C *, X, Y>{
typedef typename replace_type<C, X, Y>::type * type;
};
template <typename C, typename X, typename Y>
struct replace_type_impl<C &, X, Y>{
typedef typename replace_type<C, X, Y>::type & type;
};
template <typename C, typename X, typename Y>
struct replace_type_impl<C &&, X, Y>{
typedef typename replace_type<C, X, Y>::type && type;
};
template <typename C, typename X, typename Y>
struct replace_type_impl<C[], X, Y>{
typedef typename replace_type<C, X, Y>::type type[];
};
template <typename C, typename X, typename Y, unsigned N>
struct replace_type_impl<C [N], X, Y>{
typedef typename replace_type<C, X, Y>::type type[N];
};
template <typename C, typename Class, typename X, typename Y>
struct replace_type_impl<C Class::*, X, Y>{
typedef typename replace_type<C, X, Y>::type Class::* type;
};
template <typename R, typename X, typename Y,typename... Args>
struct replace_type_impl<R(Args...), X, Y>{
typedef typename replace_type<R, X, Y>::type type(typename replace_type<Args, X, Y>::type...);
};
}
2. 测试
#include <type_traits>
#include <gtest/gtest.h> #define MYTEST(Res, C, X , Y) EXPECT_TRUE((std::is_same<Res, xusd::replace_type<C, X, Y>::type >::value)) TEST(TestReplaceType, TestSimple){
EXPECT_TRUE((std::is_same<int*, xusd::replace_type<void*, void, int>::type >::value));
MYTEST(int*, void*, void, int);
MYTEST(long*[], int const*[], int const, long); MYTEST(int const *[], int const*[], char, long);
} TEST(TestReplaceType, TestSameType){
MYTEST(int const*[], int const*[], int const, int const); // X == Y MYTEST(long , int const*[], int const*[], long); // C == X
} TEST(TestReplaceType, TestClass){
class A;
MYTEST(long A::* , int A::*, int, long); MYTEST(long (A::*)(char, long) , int (A::*)(char, int), int, long);
}
TEST(TestReplaceType, TestReference){
MYTEST(long&&, int&&, int, long);
MYTEST(long const&&, int const&&, int, long);
MYTEST(long&, int&, int, long);
MYTEST(long const&, int const&, int, long); }
TEST(TestReplaceType, TestArray){
MYTEST(double[], int[], int , double);
MYTEST(double[], int[], int , double);
}
//TEST(TestReplaceType, TestSimple){}
TEST(TestReplaceType, TestFuntion){
EXPECT_TRUE((std::is_same<long&(*)(long&), xusd::replace_type<char&(*)(char&), char&, long&>::type >::value));
EXPECT_TRUE((std::is_same<long&(*)(long&, long&), xusd::replace_type<char&(*)(char&, char&), char&, long&>::type >::value));
EXPECT_TRUE((std::is_same<long&(*)(long&, long&, long&), xusd::replace_type<char&(*)(char&, char&, char&), char&, long&>::type >::value));
EXPECT_TRUE((std::is_same<long&(*)(long&, long&, long&, long&), xusd::replace_type<char&(*)(char&, char&, char& , char&), char&, long&>::type >::value)); EXPECT_TRUE((std::is_same<int&, xusd::replace_type<void (&)(int, long, double), void(int, long, double), int>::type >::value));
EXPECT_TRUE((std::is_same<int*, xusd::replace_type<void (*)(int, long, double), void(int, long, double), int>::type >::value)); EXPECT_TRUE((std::is_same<int(*)(char, char), xusd::replace_type<void (*)(int, long, double), void(int, long, double), int(char, char)>::type >::value));
} int main(int argc, char* argv[]){ testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
一道模板元编程题源码解答(replace_type)的更多相关文章
- 读书笔记_Effective_C++_条款四十八:了解模板元编程
作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...
- effective c++ Item 48 了解模板元编程
1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...
- 读书笔记 effective c++ Item 48 了解模板元编程
1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...
- 初识C++模板元编程(Template Mega Programming)
前言:毕设时在开源库上做的程序,但是源码看得很晕(当时导师告诉我这是模板元编程,可以不用太在乎),最近自己造轮子时想学习STL的源码,但也是一样的感觉,大致了解他这么做要干什么,但是不知道里面的机制. ...
- 初识c++模板元编程
模板元编程(Template metaprogramming,简称TMP)是编译器内执行的程序,编译器读入template,编译输出的结果再与其他源码一起经过普通编译过程生成目标文件.通俗来说,普通运 ...
- C++ 模板元编程 学习笔记
https://blog.csdn.net/K346K346/article/details/82748163 https://www.jianshu.com/p/b56d59f77d53 https ...
- C++模板元编程(C++ template metaprogramming)
实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...
- C++模板元编程 - 函数重载决议选择工具(不知道起什么好名)完成
这个还是基于之前实现的那个MultiState,为了实现三种类型“大类”的函数重载决议:所有整数.所有浮点数.字符串,分别将这三种“大类”的数据分配到对应的Converter上. 为此实现了一些方便的 ...
- C++模板元编程 - 挖新坑的时候探索到了模板元编程的新玩法
C++真是一门自由的语言,虽然糖没有C#那么多,但是你想要怎么写,想要实现什么,想要用某种编程范式或者语言特性,它都会提供. 开大数运算类的新坑的时候(又是坑),无意中需要解决一个需求:大数类需要分别 ...
随机推荐
- Hadoop学习之--Fair Scheduler作业调度分析
Fair Scheduler调度器同步心跳分配任务的过程简单来讲会经历以下环节: 1. 对map/reduce是否已经达到资源上限的循环判断 2. 对pool队列根据Fair算法排序 3.然后循环po ...
- JavaScript的function对象
我必须先说Java与JavaScript没有关系,不是我以前想的那个样子的(JavaScript是Java的一种超进化) 在JavaScript中,函数(function)就是对象. JavaScri ...
- 关于ES6扩展属性
ES6 let和const let命令 只在代码块作用域内有效 不存在变量提升(不能在申明之前赋值) 暂时性死区(在区域内不受外部变量影响) 不允许重复申明(在相同代码块区域内) 块级作用域 let为 ...
- 使用DNSPod来处理网站的均衡负载(转)
add by zhj:配置倒是蛮简单的,其实就是把域名与多个IP进行关联,在数据库中实现这个应该也是蛮简单的. 原文:http://kb.cnblogs.com/page/75571/ 首先介绍下DN ...
- 一个效果很华丽的仿桌面APP,却胜似Launcher
开发Android APP的同学是否对于Launcher实现的绚丽效果而痴迷呢?什么,连Android Launcher是什么都不知道.好吧,拿起侬的手机,在解锁后的首页界面上左右滑动滑动,体验体验, ...
- ListCell Animation in ListView
After a long time I am back again with new stuffs. I have seen that JavaFX has got so many demand no ...
- C#反射实例化类并调用类的方法
反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力. 它允许程序创建和控制任何类的对象,无需提前硬编码目标类: SalBLL a = (SalBLL)Assembly.Load("B ...
- nyoj117 求逆序数
求逆序数 时间限制:2000 ms | 内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中 ...
- Umbraco中更换IndexSet中的NodeType后,搜索页面没有做出对应更改的效果
在项目开发中,使用ExternalSearcher,有一个ExamineIndex.config文件中存放ExternalIndexSet 开始时是这样的 <!-- Default Indexs ...
- lighttpd fastcgi的搭建
公司很久以前有个task需要在板子上搭建个webserver以响应局域网内手机的请求. 以前是用lighttpd plugin实现的,后来仔细想想用fast cgi来弄也可以. 在install li ...