今天有一同学在群上聊到一个比较好玩的题目(本人看书不多,后面才知是《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)的更多相关文章

  1. 读书笔记_Effective_C++_条款四十八:了解模板元编程

    作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...

  2. effective c++ Item 48 了解模板元编程

    1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...

  3. 读书笔记 effective c++ Item 48 了解模板元编程

    1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...

  4. 初识C++模板元编程(Template Mega Programming)

    前言:毕设时在开源库上做的程序,但是源码看得很晕(当时导师告诉我这是模板元编程,可以不用太在乎),最近自己造轮子时想学习STL的源码,但也是一样的感觉,大致了解他这么做要干什么,但是不知道里面的机制. ...

  5. 初识c++模板元编程

    模板元编程(Template metaprogramming,简称TMP)是编译器内执行的程序,编译器读入template,编译输出的结果再与其他源码一起经过普通编译过程生成目标文件.通俗来说,普通运 ...

  6. C++ 模板元编程 学习笔记

    https://blog.csdn.net/K346K346/article/details/82748163 https://www.jianshu.com/p/b56d59f77d53 https ...

  7. C++模板元编程(C++ template metaprogramming)

    实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...

  8. C++模板元编程 - 函数重载决议选择工具(不知道起什么好名)完成

    这个还是基于之前实现的那个MultiState,为了实现三种类型“大类”的函数重载决议:所有整数.所有浮点数.字符串,分别将这三种“大类”的数据分配到对应的Converter上. 为此实现了一些方便的 ...

  9. C++模板元编程 - 挖新坑的时候探索到了模板元编程的新玩法

    C++真是一门自由的语言,虽然糖没有C#那么多,但是你想要怎么写,想要实现什么,想要用某种编程范式或者语言特性,它都会提供. 开大数运算类的新坑的时候(又是坑),无意中需要解决一个需求:大数类需要分别 ...

随机推荐

  1. STL map 用法

    首先make_pair Pairs C++标准程序库中凡是"必须返回两个值"的函数, 也都会利用pair对象  class pair可以将两个值视为一个单元.容器类别map和mul ...

  2. 【多线程同步案例】Race Condition引起的性能问题

    Race Condition(也叫做资源竞争),是多线程编程中比较头疼的问题.特别是Java多线程模型当中,经常会因为多个线程同时访问相同的共享数据,而造成数据的不一致性.为了解决这个问题,通常来说需 ...

  3. Dagger2 scope

    1. 一个没有scope的component是不能依赖于另外一个有scope的component 2.@Singleton不是真正意义的单例,比如下面 @Singleton @Component cl ...

  4. DMOZ介绍以及如何提交

    转载自 http://www.cnblogs.com/freespider/archive/2009/12/28/1633818.html Dmoz介绍及怎么提交? 1.Dmoz目录简介: Dmoz是 ...

  5. Android_UI_点击按钮切换背景效果实现

    实现按钮按下和释放,按钮背景图片相应切换效果的方法这里介绍两种,一种是在代码里实现,另一种是在xml文件里实现 一.在xml文件里 首先现在layout的一个xml文件下定义Button如下所示: [ ...

  6. POJ2155Matrix(二维线段树)

    链接http://poj.org/problem?id=2155 题目操作就是说,每次操作可以是编辑某个矩形区域,这个区域的0改为1,1改为0,每次查询只查询某一个点的值是0还是1. 方法:二维线段树 ...

  7. C#中的DllImport

    大家在实际工作学习C#的时候,可能会问:为什么我们要为一些已经存在的功能(比如 Windows中的一些功能,C++中已经编写好的一些方法)要重新编写代码,C#有没有方法可以直接都用这些原本已经存在的功 ...

  8. PostQueuedCompletionStatus

    PostQueuedCompletionStatus函数,向每个工作者线程都发送—个特殊的完成数据包.该函数会指示每个线程都“立即结束并退出”.下面是PostQueuedCompletionStatu ...

  9. Thinkphp模板怎么使用自定义函数

    内置模板引擎支持对模板变量使用函数,并支持多个函数同时使用. 注意:自定义函数要放在项目应用目录/common/common.php中. 这里是关键. 模板变量的函数调用格式:{$varname|fu ...

  10. MyEclipse 8.6反编译插件安装

    一.下载插件文件:jad.exe.jadeclipse    http://www.varaneckas.com/sites/default/files/jad/jad158g.win.zip    ...