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