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

 

 

 

 

 

 

你可能感兴趣的:(replace)