一道模板元编程题源码解答(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*[10]
, 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. 测试

 1 #include <type_traits>
2 #include <gtest/gtest.h>
3
4 #define MYTEST(Res, C, X , Y) EXPECT_TRUE((std::is_same<Res, xusd::replace_type<C, X, Y>::type >::value))
5
6 TEST(TestReplaceType, TestSimple){
7 EXPECT_TRUE((std::is_same<int*, xusd::replace_type<void*, void, int>::type >::value));
8 MYTEST(int*, void*, void, int);
9 MYTEST(long*[10], int const*[10], int const, long);
10
11 MYTEST(int const *[10], int const*[10], char, long);
12 }
13
14 TEST(TestReplaceType, TestSameType){
15 MYTEST(int const*[10], int const*[10], int const, int const); // X == Y
16
17 MYTEST(long , int const*[10], int const*[10], long); // C == X
18 }
19
20
21 TEST(TestReplaceType, TestClass){
22 class A;
23 MYTEST(long A::* , int A::*, int, long);
24
25 MYTEST(long (A::*)(char, long) , int (A::*)(char, int), int, long);
26 }
27 TEST(TestReplaceType, TestReference){
28 MYTEST(long&&, int&&, int, long);
29 MYTEST(long const&&, int const&&, int, long);
30 MYTEST(long&, int&, int, long);
31 MYTEST(long const&, int const&, int, long);
32
33 }
34 TEST(TestReplaceType, TestArray){
35 MYTEST(double[], int[], int , double);
36 MYTEST(double[10], int[10], int , double);
37 }
38 //TEST(TestReplaceType, TestSimple){}
39 TEST(TestReplaceType, TestFuntion){
40 EXPECT_TRUE((std::is_same<long&(*)(long&), xusd::replace_type<char&(*)(char&), char&, long&>::type >::value));
41 EXPECT_TRUE((std::is_same<long&(*)(long&, long&), xusd::replace_type<char&(*)(char&, char&), char&, long&>::type >::value));
42 EXPECT_TRUE((std::is_same<long&(*)(long&, long&, long&), xusd::replace_type<char&(*)(char&, char&, char&), char&, long&>::type >::value));
43 EXPECT_TRUE((std::is_same<long&(*)(long&, long&, long&, long&), xusd::replace_type<char&(*)(char&, char&, char& , char&), char&, long&>::type >::value));
44
45 EXPECT_TRUE((std::is_same<int&, xusd::replace_type<void (&)(int, long, double), void(int, long, double), int>::type >::value));
46 EXPECT_TRUE((std::is_same<int*, xusd::replace_type<void (*)(int, long, double), void(int, long, double), int>::type >::value));
47
48 EXPECT_TRUE((std::is_same<int(*)(char, char), xusd::replace_type<void (*)(int, long, double), void(int, long, double), int(char, char)>::type >::value));
49 }
50
51
52 int main(int argc, char* argv[]){
53
54 testing::InitGoogleTest(&argc, argv);
55 return RUN_ALL_TESTS();
56 }

一道模板元编程题源码解答(replace_type),布布扣,bubuko.com

时间: 2024-10-27 07:59:16

一道模板元编程题源码解答(replace_type)的相关文章

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

前言:毕设时在开源库上做的程序,但是源码看得很晕(当时导师告诉我这是模板元编程,可以不用太在乎),最近自己造轮子时想学习STL的源码,但也是一样的感觉,大致了解他这么做要干什么,但是不知道里面的机制.于是开始学习<C++模板元编程>,看完第二章对一些东西豁然开朗. PS:该书也有点老了,C++11标准还没出来,主要用的Boost库. Traits(特征) 说正题,在STL中经常可以见到后缀为traits的名字,比如经常用到的std::string,本质是类模板basic_string的第一个参

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

1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在C++编译器内部运行的一个程序,它的输出——从模板中实例化出来的C++源码片段——会像往常一样被编译. 2. 使用TMP的优势 如果这没有冲击到你,是因为你没有足够尽力去想. C++不是为了模板元编程而设计的,但是自从TMP早在1990年被发现之后,它就被证明是非常有用的,为了使TMP的使用更加容易

Qt元对象系统源码解析

Qt元对象系统源码解析 https://blog.51cto.com/9291927/2070348 一.Qt元对象系统简介 1.元对象系统简介 Qt 的信号槽和属性系统基于在运行时进行内省的能力,所谓内省是指面向对象语言的一种在运行期间查询对象信息的能力, 比如如果语言具有运行期间检查对象型别的能力,那么是型别内省(type intropection)的,型别内省可以用来实施多态.C++的内省比较有限,仅支持型别内省, C++的型别内省是通过运行时类型识别(RTTI)(Run-Time Typ

C++模板元编程 - 2 模仿haskell的列表以及相关操作

这是昨天和今天写的东西,利用C++的可变模板参数包以及包展开,模式匹配的一些东西做的,感觉用typename...比轮子叔那个List<A,List<B, List<C, D>>>的设计要好看不少. List有一个很巧妙的继承,只有那么做才能使用类似于List<>::Rest的写法,直接定义成template<typename T, typename... TArgs>List是不行的. Change这里可以给一个args...换另一个包装,这里

C++拾遗--模板元编程

C++拾遗--模板元编程 前言 模板元是用于递归加速的,把运行期的函数调用变到编译期进行代码展开,类似于内联函数.下面看一个实例:斐波那契数列第n项求解. 模板元编程 #include <iostream> #include <ctime> using namespace std; //递归法 int fib(int n) { if (n < 0) return 0; if (n == 1 || n == 2) return 1; return fib(n - 1) + fi

模板元编程

//模板元把运行时消耗的时间,在编译期间优化 //递归极其消耗时间 1 #include <iostream> 2 3 //模板元把运行时消耗的时间,在编译期间优化 4 //递归极其消耗时间 5 6 template <int N> 7 struct data 8 { 9 enum { res = data<N - 1>::res + data<N - 2>::res }; 10 }; 11 12 template <> 13 struct da

模板元编程加速递归

//模板元编程加速递归 //缺点:模板元在编译时处理,无法调试,并且会加大代码体积 #include<iostream> using namespace std; template <int N> struct data { enum{res = data<N - 1>::res + data<N - 2>::res}; }; template <>//模板具体化 struct data<1> { enum{res = 1}; };

【C/C++学院】0816-引用包装器/仿函数/转义字符 R”()”/using别名/模板元编程 比递归优化/智能指针/多线程/静态断言以及调试技能的要求 assert

引用包装器  std::ref(变量) #include<iostream> template<class T> void com(T arg)//模板函数,引用无效,引用包装器 { std::cout <<"com ="<< &arg << "\n"; arg++; } void main() { int count = 10; int & rcount = count; com(coun

C++模板元编程 - 3 逻辑结构,递归,一点列表的零碎,一点SFINAE

本来想把scanr,foldr什么的都写了的,一想太麻烦了,就算了,模板元编程差不多也该结束了,离开学还有10天,之前几天部门还要纳新什么的,写不了几天代码了,所以赶紧把这个结束掉,明天继续抄轮子叔的Win32库去. 逻辑结构和递归说白了就是做了一个If,一个For_N,If就和Excel里的If一样,For_N是把一个模板结构迭代N遍,为了所谓的方便,把If做成了宏,写起来还挺有意思的 1 template<typename TTest, typename TTrue, typename TF