<>3.12节一段代码不懂.谁帮忙看看呀?

cunsh 2006-04-20 01:31:53
这里有两个模板:
MostDerived和DerivedToFront
MostDerived得到一个类T在一个Typelist中的最终派生类.
DerivedToFront将一个Typelist中的派生类放在基类之前.

代码如下:


//MostDerived

template <class TList, class T> struct MostDerived;

template <class T>
struct MostDerived<NullType, T> {
typedef T Result;
};

template <class Head, class Tail, class T>
struct MostDerived<Typelist<Head, Tail>, T> {
private:
typedef typename MostDerived<Tail, T>::Result Candidate;
public:
typedef typename Select< SUPERSUBCLASS(Candidate, Head),
Head, Candidate>::Result Result;
};


//然后用MostDerived来实现DerivedToFront:

template<class T>struct DerivedToFront;

typelate<> struct DerivedToFront<NulType> {
typedef NullType Result;
};

typedef <class Head , class Tail>
struct DerivedToFront<Typelist<Head, Tail> > {
private:
typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
typedef typename Replace<Tail, TheMostDerived, Head>::Result L;
public:
typedef Typelist<TheMostDerived, L> Result; //这里的Result是什么?如何工作的?.
};


其中的DerivedToFront是怎么工作的没看懂.谁给讲讲呀?
...全文
373 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
cunsh 2006-04-23
  • 打赏
  • 举报
回复

原来是其他位置上的都不变. 我把这个模板的功能想错了.

谢谢帮助.

结帖.
sharpdew 2006-04-23
  • 打赏
  • 举报
回复
准确地说是把Replace的模板参数<Tail, TheMostDerived, Head>第一个参数Tail这个Typelist中与TheMostDerived相同的类型由Head替换掉,并把这个替换后的Typelist作为Replace的Result。
sharpdew 2006-04-23
  • 打赏
  • 举报
回复
准确地说是把Replace的模板参数<Tail, TheMostDerived, Head>中的与TheMostDerived相同的类型由替换掉,并把其作为Replace的Result。
pacman2000 2006-04-23
  • 打赏
  • 举报
回复
呵呵,虽然有点不太好理解,但是DerivedToFront只是把MostDerived和Head做了个替换。并没改变其他的位置。
sharpdew 2006-04-23
  • 打赏
  • 举报
回复
下面是针对L3以及L4的编译解析过程,对于Replace<Tail, TheMostDerived, Head>来说,Replace总是把Head替换掉TheMostDerived并把Head置于Typelist的最后,而对于MostDerived<Tail, Head>来说,对L4其求得的最下层继承类就是D,这是由其计算顺序得到的,如果把C放到最后,就会求得C为the most derived class. 把L4改为TYPELIST_4(A, B, D, C)就知道。
int main_L3(void)
{
cout << "MostDerived:" << endl;
cout << typeid( MostDerived<TYPELIST_2(B,C),A> ::Result ).name() << endl; /// 对应 -- typedef typename MostDerived<TYPELIST_2(B,C), A>::Result TheMostDerived;

cout << "Replace:" << endl;
cout << typeid( Replace<TYPELIST_2(B,C), C, A>::Result ).name() << endl; /// 对应 -- typedef typename Replace<TYPELIST_2(B,C), C, A>::Result L;

cout << "DerivedToFront:" << endl;
cout << typeid( DerivedToFront<L3>::Result ).name() << endl; /// 对应 -- typedef Typelist<C, L> Result;

return 0;
}

int main_L4(void)
{
cout << "MostDerived:" << endl;
cout << typeid( MostDerived<TYPELIST_3(B,C,D),A> ::Result ).name() << endl; /// 对应 -- typedef typename MostDerived<TYPELIST_3(B,C,D), A>::Result TheMostDerived;

cout << "Replace:" << endl;
cout << typeid( Replace<TYPELIST_3(B,C,D), D, A>::Result ).name() << endl; /// 对应 -- typedef typename Replace<TYPELIST_3(B,C,D), D, A>::Result L;

cout << "DerivedToFront:" << endl;
cout << typeid( DerivedToFront<L4>::Result ).name() << endl; /// 对应 -- typedef Typelist<D, L> Result;

return 0;
}

sharpdew 2006-04-23
  • 打赏
  • 举报
回复
这个解释起来有点麻烦,我待会写个例子解释L4的情况
cunsh 2006-04-23
  • 打赏
  • 举报
回复
谢谢大家.

to : 风刃

你的例子中的L4 是 A B C D
从输出的结果看 DerivedToFront<L4>::Result 是 D B C A

就是说 B 是 C 的基类. 但 B 怎么还在 C 之前啊?.
sharpdew 2006-04-23
  • 打赏
  • 举报
回复
cunsh(村少) 你应该这样测试,pacman2000(pacman)(影子传说) 说的没错,这是利用模板定义在编译递归求解类的继承层次,从最下面的继承类型开始依次求解其父类型并由Typelist表示。

typedef TYPELIST_1(A) L1;

typedef TYPELIST_2(A, B) L2;

typedef TYPELIST_3(A, B, C) L3;

typedef TYPELIST_3(A, B, D) L3_1;

typedef TYPELIST_4(A, B, C, D) L4;
int main(void)
{
cout << "DerivedToFront:" << endl;
cout << typeid( DerivedToFront<L1>::Result ).name() << endl;
cout << typeid( DerivedToFront<L2>::Result ).name() << endl;
cout << typeid( DerivedToFront<L3>::Result ).name() << endl;
cout << typeid( DerivedToFront<L3_1>::Result ).name() << endl;
cout << typeid( DerivedToFront<L4>::Result ).name() << endl;

return 0;
}
pacman2000 2006-04-23
  • 打赏
  • 举报
回复
呵呵,先up一下。
cunsh 2006-04-21
  • 打赏
  • 举报
回复

帮忙看看. 大家讲讲义气呀?
sharpdew 2006-04-21
  • 打赏
  • 举报
回复
闲着也是闲着,回去给你看看,呵呵
cunsh 2006-04-20
  • 打赏
  • 举报
回复
up
逸学堂 2006-04-20
  • 打赏
  • 举报
回复
这只是一个回顾,上面的简单程序就不用我解释了吧?下面的这个 remove_cv 算法会去掉参数类型的 const 和 volatile 修饰符(如果有的话),Boost type_traits 就是这么干的。

#include <iostream>

using namespace std;

template <class T> struct remove_cv
{ typedef T type; };

template <class T> struct remove_cv<const volatile T>
{ typedef T type; };

template <class T> struct remove_cv<const T>
{ typedef T type; };

template <class T> struct remove_cv<volatile T>
{ typedef T type; };

int main()
{
cout << "remove_cv<const int>: "
<< typeid(remove_cv<const int>::type).name() << endl;
cout << "remove_cv<volatile int>: "
<< typeid(remove_cv<volatile int>::type).name() << endl;
cout << "remove_cv<const volatile int>: "
<< typeid(remove_cv<const volatile int>::type).name() << endl;
}

输出:

remove_cv<const int>: int
remove_cv<volatile int>: int
remove_cv<const volatile int>: int

这个也很简单,但是非常有用。最后再来一个,相当有用的,它让我们可以在编译期间把一个数字作为二进制数来解释:

#include <iostream>

using namespace std;

template <unsigned long N>
struct binary
{
static unsigned const value =
binary<N/10>::value << 1 | N%10;
};

template <>
struct binary<0>
{
static unsigned const value = 0;
};

int main()
{
cout << "binary<1>: " << binary<1>::value << endl;
cout << "binary<11>: " << binary<11>::value << endl;
cout << "binary<101>: " << binary<101>::value << endl;
cout << "binary<111>: " << binary<111>::value << endl;
cout << "binary<1011101>: " << binary<1011101>::value << endl;
}

输出:

binary<1>: 1
binary<11>: 3
binary<101>: 5
binary<111>: 7
binary<1011101>: 93

不过上面这个程序不容错,换句话说,如果你写 binary<123>::value ,编译器不会阻止你,还会给出一个愚蠢的答案。如果要做一个容错的解释器,只需要玩一个小小的把戏(本人原创):
逸学堂 2006-04-20
  • 打赏
  • 举报
回复
lz,刚才看了一下。
这应该是Template metaprogramming(模板元编程)。是一个递归调用,这里在编译时刻完成的递归调用。
其特性就是使用模板的特化和半特化。给你举一个简单的例子

template<int n>
class fact
{
public:
enum { value = n * fact::value };
};

template<>
class fact<0>
{
public:
enum { value = 1 };
};

int main(int argc, char* argv[])
{
std::cout << 479001600 << endl;
std::cout << fact<12>::value << std::endl;
}
上面的例子,就是一个递归调用,利用模板的特化来终结递归。

我的网站有两篇关于模板元编程文章,lz参考一下

http://www.exuetang.net/article/View.aspx?NewsID=183
http://www.exuetang.net/article/View.aspx?NewsID=182

希望村少有所借鉴。

cunsh 2006-04-20
  • 打赏
  • 举报
回复


template <class Head , class Tail>
struct DerivedToFront<Typelist<Head, Tail> > {
private:
typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
typedef typename Replace<Tail, TheMostDerived, Head>::Result L;
public:
typedef Typelist<TheMostDerived, L> Result; //这里如何递归没有看懂.
};

总之这儿没看出一句递归的代码. 是不是书上印错了啊?
cunsh 2006-04-20
  • 打赏
  • 举报
回复

还是不对呀. 我把下边这些抄到devc++里运行看了下:



#include <iostream>
using namespace std;

class NullType;

template <class T, class U>
struct Typelist
{
typedef T Head;
typedef U Tail;
};

#define TYPELIST_1(T1) Typelist<T1, NullType>
#define TYPELIST_2(T1, T2) Typelist<T1, Typelist<T2, NullType> >
#define TYPELIST_3(T1, T2, T3) Typelist<T1, Typelist<T2, Typelist<T3, NullType> > >
#define TYPELIST_4(T1, T2, T3, T4) Typelist<T1, Typelist<T2, Typelist<T3, Typelist<T4, NullType> > > >
////////////////////////

template <bool flag, typename T, typename U>
struct Select {
typedef T Result;
};

template < typename T, typename U>
struct Select < false, T, U> { //偏特化一个版本
typedef U Result;
};

////////////////////

template <class T, class U>
class Conversion {
typedef char Small;
class Big { char XXX[2]; };
static Small Test(U);
static Big Test(...);
static T MakeT();
public:
//T可以转换到U类型?
enum { exists = sizeof(Test(MakeT())) == sizeof(Small) };
//T和U两个类型可以相互转换?
enum { exists2Way = exists && Conversion<U,T>::exists };
//T和U是相同类型?
enum { sameType = false }; //下边将相同类型时的版本偏特化出
};
//为 T和U 是相同类型的情况偏特化一个:
template<class T>
class Conversion<T,T> {
public:
enum { exists = 1, exists2Way = 1, sameType = 1 } ;
};
//继承性探测
#define SUPERSUBCLASS(T, U) \
( Conversion <const U*, const T*>::exists && \
!Conversion<const T* , const void *>::sameType && \
!Conversion<const T, const U>::sameType )


//////////////////
class NullType;

//用Replace .

template <class TList, class T, class U> struct Replace ;

template <class T, class U>
struct Replace<NullType, T, U> {
typedef NullType Result;
};

template <class Tail, class T, class U>
struct Replace<Typelist<T, Tail> , T, U> {
typedef Typelist<U, Tail> Result;
};

template <class Head, class Tail, class T, class U>
struct Replace<Typelist<Head, Tail>, T, U> {
typedef Typelist<Head, typename Replace<Tail,T,U>::Result>
Result;
};

///////////////////////////////////

template <class TList, class T> struct MostDerived;

template <class T>
struct MostDerived<NullType, T> {
typedef T Result;
};

template <class Head, class Tail, class T>
struct MostDerived<Typelist<Head, Tail>, T> {
private:
typedef typename MostDerived<Tail, T>::Result Candidate;
public:
typedef typename Select< SUPERSUBCLASS(Candidate, Head),
Head, Candidate>::Result Result;
};

///////////////////////////////////////////

template<class T>struct DerivedToFront;

template<> struct DerivedToFront<NullType> {
typedef NullType Result;
};

template <class Head , class Tail>
struct DerivedToFront<Typelist<Head, Tail> > {
private:
typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
typedef typename Replace<Tail, TheMostDerived, Head>::Result L;
public:
typedef Typelist<TheMostDerived, L> Result; //这里如何递归没有看懂.
};

///////////////////////////////////////////

//上面全是从书上抄下来的.下边是我试验的代码:

class A {};
class B : public A{};
class C : public B{};
class D : public A{};

typedef TYPELIST_4(D, B, C, A) L1;

typedef TYPELIST_4(D, C, B, A) L2;


void func( L1 ) {cout << "L1" << endl; }
void func( L2 ) {cout << "L2" << endl; }

int main(void)
{
func( DerivedToFront<L1>::Result() ); //这里输出的还是 L1
cin.get();
return 0;
}

// 上边的L1 中的顺序是 D, B, C, A .其中C是B的派生类,
// DerivedToFront<L1>::Result 返回后 C应该放在B之前 即 D C B A 的顺序.
// 但输出的结果L1说明顺序还是D, B, C, A
// 这到底怎么回事呀??
cunsh 2006-04-20
  • 打赏
  • 举报
回复

晕. 我上面好多template这个单词都拼错了.. 昨晚抄的时候抄错很多啊.

我再看下.
pacman2000 2006-04-20
  • 打赏
  • 举报
回复
首先,typedef typename MostDerived<Tail, Head>::Result TheMostDerived; 这个是求出Head到Tail中的最深层次类。
然后,typedef typename Replace<Tail, TheMostDerived, Head>::Result L; 用了个replace算法,来把Tail中的TheMostDerived类替换成Head类。这样相当于Head和TheMostDerived换了个位置。
最后返回typedef Typelist<TheMostDerived, L> Result,就是把TheMostDerived放到最前了。
pacman2000 2006-04-20
  • 打赏
  • 举报
回复
就是把typelist中深层次的替换到列表的前面去啊。
cunsh 2006-04-20
  • 打赏
  • 举报
回复

书上说这个 Typelist 是 Loki 中的. 熟悉的帮忙看看啊?
加载更多回复(3)

64,676

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧