首页 > 代码库 > 一道模板元编程题源码解答(replace_type)

一道模板元编程题源码解答(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 }
View Code