用户操作
[即时聊天] [发私信] [加为好友]
pandaID:pandaxcl
86216次访问,排名1155,好友16人,关注者17人。
pandaxcl的文章
原创 62 篇
翻译 0 篇
转载 0 篇
评论 168 篇
pandaxcl的公告

博客文档资源下载在本人的网站下载!!!

我也优先在我的网站论坛上面回答问题

在研究C++自动化编程好久之后,发现C++自动化编程在国内还是一个空白。所谓的C++自动化编程,简单点说就是采用了C++的高级模板技术配合产生式编程技法实现了C++代码的自我配置,自动维护代码之间的种种一致性问题。关于这个问题的讨论,将会在我的网站上面进行细致的讨论。如果有问题,欢迎来我的网站提问哦。看看下面的我的网站的链接。

EMail:pandaxcl@163.com

QQ:56637059

我的网站: http://www.autodev.net

最近评论
pandaxcl:boost里面的mpl是模板元编程的基础结构,而我的这个库目的在于应用模板元到实际的编程中,有很大的区别:)
pandaxcl:呵呵:)这里的any和BOOST里面的any完全是两回事:)
不一样哈;)
whinah:还有boost.spirit,虽然编译速度慢了一点,但是效果很好
whinah:还有boost.spirit,虽然编译速度慢了一点,但是效果很好
whinah:别走火入魔了,你的这个库,boost里面都有,boost.mpl,boost.type_traits,boost.pp
文章分类
收藏
    相册
    友情连接
    小熊猫
    我的另外一个博客
    我的网站-自动化编程社区
    我的论坛-自动化编程社区论坛
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 C++自动化(模板元)编程基础与应用(6)收藏

    新一篇: 撤销和重做(Undo和Redo)的C++完美实现(9) | 旧一篇: 撤销和重做(Undo和Redo)的C++完美实现(8-B)

    #if 0

    在上一章里面讨论了代码的自动生成机制,经常会遇到根据不同的类型选择不同的操
    作的情况,也就是静态分派的问题。这就需要有一种机制用来识别不同的类型,在本章里
    面将会系统的讨论C++里面可用的类型识别问题。

    最常见的有下面几种:

    (1)根据模板参数需要精确匹配类型来识别类型

    (2)根据隐式自动转型来判断类型是否可以自动转型,从而可以判断是某个基类的派生
    类。

    (3)给每一个类型都追加一个额外的模板参数用来表示不同的类型,一般都是用不同的
    数字映射为不同的类型来实现类型识别的,前面讨论的可以有重复类型的scatter代码产生
    器就采用了这种方法来识别不同的类型的。

    在这一章里面将会分别讨论上面的三种情况的一般应用:

    #endif
    #ifdef CODE1//g++ -DCODE1 thisfile.cpp
    //采用方法(1)来识别不同的类型
    #include <iostream>
    #include <string>
    #include <complex>
    template <class T>struct traits;
    template <> struct traits<char > {static const char*name(){return "char ";}};
    template <> struct traits<int > {static const char*name(){return "int ";}};
    template <> struct traits<short > {static const char*name(){return "short ";}};
    template <> struct traits<long > {static const char*name(){return "long ";}};
    template <> struct traits<float > {static const char*name(){return "float ";}};
    template <> struct traits<double> {static const char*name(){return "double";}};
    template <> struct traits<std::string>
    {
    static const char*name(){return "std::string";}
    };
    template <> struct traits<std::complex<float > >
    {
    static const char*name(){return "std::complex<float>";}
    };
    template <> struct traits<std::complex<double> >
    {
    static const char*name(){return "std::complex<double>";}
    };
    int main()
    {
    std::cout<<"char :["<<traits<char >::name()<<"]"<<std::endl;
    std::cout<<"int :["<<traits<int >::name()<<"]"<<std::endl;
    std::cout<<"short :["<<traits<short >::name()<<"]"<<std::endl;
    std::cout<<"long :["<<traits<long >::name()<<"]"<<std::endl;
    std::cout<<"float :["<<traits<float >::name()<<"]"<<std::endl;
    std::cout<<"double:["<<traits<double>::name()<<"]"<<std::endl;
    std::cout<<"std::string:["<<traits<std::string>::name()<<"]"<<std::endl;
    std::cout<<"std::complex<float >:["<<traits<std::complex<float > >::name()<<"]"<<std::endl;
    std::cout<<"std::complex<double>:["<<traits<std::complex<double> >::name()<<"]"<<std::endl;
    return 0;
    }
    #endif//CODE1
    ////////////////////////////////////////////////////////////////////////////////
    //该程序的运行结果:
    /*******************************************************************************
    char :[char ]
    int :[int ]
    short :[short ]
    long :[long ]
    float :[float ]
    double:[double]
    std::string:[std::string]
    std::complex<float >:[std::complex<float>]
    std::complex<double>:[std::complex<double>]
    *******************************************************************************/
    ////////////////////////////////////////////////////////////////////////////////
    #if 0

    从CODE1的运行结果可以看出:已经成功的分辨出了各个不同的类型。但是我们还是可
    以看出为了能够分辨出不同的类型需要编写大量的代码,对于基础类型这是不可避免的,
    但是值得庆幸的是C++里面的基本类型是有限的,所以作为一个库的编写者来说完全可采用
    穷举的方法来完成的。但是我们可以看出针对于CODE1中的std::complex<float>和std::
    complex<double>来说,它们实际上是一种模板代码,不同的模板参数完全可产生出无数的
    类型出来,对于这样的模板类型来说,采用穷举的方法恐怕就不行了。当然这里的复数类
    一般就只会使用float和double来作为模板参数,但是对于判断某个型别是否是某个模板类
    型以及判断某个类型是否是某个模板类型的派生类就力不足心了。为了便于讨论这个问题
    ,我们假定这个模板类型只有一个模板参数。参见下面的代码:

    #endif
    #ifdef CODE_NOTE
    //某个模板类
    template <class T>struct Template{};
    //某个模板类的派生类
    template <class T>struct Derived:public Template<T>{};
    #endif//CODE_NOTE
    #if 0

    对于上面的Template模板类来说同样可以采用CODE1中的方案来实现类型识别的,参看
    CODE2中的测试代码:

    #endif
    #ifdef CODE2//g++ -DCODE2 thisfile.cpp
    #include <iostream>
    #include <string>
    #include <complex>
    //某个模板类
    template<class T>struct Template{};
    //识别这个模板类的方法:
    template <class T> struct traits{static const char*name(){return "Is not kind of Template";}};
    template <class T> struct traits<Template<T> >{static const char*name(){return "Is kind of Template";}};
    template <class T> struct traits<std::complex<T> >{static const char*name(){return "Is kind of std::complex";}};
    int main()
    {
    std::cout << "char :[" << traits<Template<char > >::name() << "]" << std::endl;
    std::cout << "int :[" << traits<Template<int > >::name() << "]" << std::endl;
    std::cout << "short :[" << traits<Template<short > >::name() << "]" << std::endl;
    std::cout << "long :[" << traits<Template<long > >::name() << "]" << std::endl;
    std::cout << "float :[" << traits<Template<float > >::name() << "]" << std::endl;
    std::cout << "double:[" << traits<Template<double> >::name() << "]" << std::endl;
    std::cout << "std::string:[" << traits<Template<std::string> >::name() << "]" << std::endl;
    std::cout << "std::complex<float> :[" << traits<std::complex<float > >::name() << "]" << std::endl;
    std::cout << "std::complex<double>:[" << traits<std::complex<double> >::name() << "]" << std::endl;
    return 0;
    }
    #endif//CODE2
    ////////////////////////////////////////////////////////////////////////////////
    //该程序的运行结果:
    /*******************************************************************************
    char :[Is kind of Template]
    int :[Is kind of Template]
    short :[Is kind of Template]
    long :[Is kind of Template]
    float :[Is kind of Template]
    double:[Is kind of Template]
    std::string:[Is kind of Template]
    std::complex<float> :[Is kind of std::complex]
    std::complex<double>:[Is kind of std::complex]
    *******************************************************************************/
    ////////////////////////////////////////////////////////////////////////////////
    #if 0

    从CODE2的运行结果可以看出:我们已经成功的识别出了同一个模板类实例化出来的所
    有的类型。现在我们就来考虑一下如何识别出某个模板类的派生类的问题,也就前面提到
    的Derived类型的识别问题。对于这种问题就不可能用前面第一种方法来识别了。这个时候
    就是第二种识别方法隆重登场的时候了。参见CODE3的代码:

    #endif
    #ifdef CODE3//g++ -DCODE3 thisfile.cpp
    #include <iostream>
    #include <string>
    #include <complex>
    //某个模板类
    template <class T>struct Template{};
    //另一个模板类
    template <class T>struct AnotherTemplate{};
    //某个模板类的派生类,可以有无数种
    struct Derived1:public Template<char >{};
    struct Derived2:public Template<int >{};
    struct Derived3:public Template<short >{};
    struct Derived4:public Template<long >{};
    struct Derived5:public Template<float >{};
    struct Derived6:public Template<double>{};
    struct Derived7:public Template<std::string>{};
    struct Derived8:public Template<std::complex<float > >{};
    struct Derived9:public Template<std::complex<double> >{};
    //考虑到这种情况必须采用一种映射关系,将所有的Template模板类的派生类都映射成为
    //Template类型,注意哦,这里是映射而不是转型哦!映射到了Template类型之后再采用
    //比较这个类型和参数类型的尺寸的方法来实现识别功能,具体代码如下:
    template <class T,template<class>class TemplateType>
    class is_kind_of
    {
    //定义一个类型来表示任意类型
    typedef char AnyType;
    //定义一个类型来表示指定的类型
    class SpecifiedType {char unnamed[2];};
    //完成任意类型映射成为AnyType的功能
    static AnyType Map(...);
    //完成指定模板类型映射成为SpecifiedType的功能
    //这里还使用了函数传递参数的时候隐式转型的能力
    template<class PT>
    static SpecifiedType Map(TemplateType<PT>);
    public:
    //通过计算映射之后的两个类型的尺寸来识别类型
    enum{
    //传递参数的时候让编译器来自动选择合适的Map函数以完成类型映射功
    //能
    yes=(sizeof(Map(T()))==sizeof(SpecifiedType)),
    no =(sizeof(Map(T()))==sizeof(AnyType))
    };
    };
    //下面是测试代码
    int main()
    {
    std::cout << "Derived1 is kind of Template? " << is_kind_of<Derived1,Template>::yes << std::endl;
    std::cout << "Derived2 is kind of Template? " << is_kind_of<Derived2,Template>::yes << std::endl;
    std::cout << "Derived3 is kind of Template? " << is_kind_of<Derived3,Template>::yes << std::endl;
    std::cout << "Derived4 is kind of Template? " << is_kind_of<Derived4,Template>::yes << std::endl;
    std::cout << "Derived5 is kind of Template? " << is_kind_of<Derived5,Template>::yes << std::endl;
    std::cout << "Derived6 is kind of Template? " << is_kind_of<Derived6,Template>::yes << std::endl;
    std::cout << "Derived7 is kind of Template? " << is_kind_of<Derived7,Template>::yes << std::endl;
    std::cout << "Derived8 is kind of Template? " << is_kind_of<Derived8,Template>::yes << std::endl;
    std::cout << "Derived9 is kind of Template? " << is_kind_of<Derived9,Template>::yes << std::endl;

    std::cout << "Derived1 is kind of AnotherTemplate? " << is_kind_of<Derived1,AnotherTemplate>::yes << std::endl;
    std::cout << "Derived2 is kind of AnotherTemplate? " << is_kind_of<Derived2,AnotherTemplate>::yes << std::endl;
    std::cout << "Derived3 is kind of AnotherTemplate? " << is_kind_of<Derived3,AnotherTemplate>::yes << std::endl;
    std::cout << "Derived4 is kind of AnotherTemplate? " << is_kind_of<Derived4,AnotherTemplate>::yes << std::endl;
    std::cout << "Derived5 is kind of AnotherTemplate? " << is_kind_of<Derived5,AnotherTemplate>::yes << std::endl;
    std::cout << "Derived6 is kind of AnotherTemplate? " << is_kind_of<Derived6,AnotherTemplate>::yes << std::endl;
    std::cout << "Derived7 is kind of AnotherTemplate? " << is_kind_of<Derived7,AnotherTemplate>::yes << std::endl;
    std::cout << "Derived8 is kind of AnotherTemplate? " << is_kind_of<Derived8,AnotherTemplate>::yes << std::endl;
    std::cout << "Derived9 is kind of AnotherTemplate? " << is_kind_of<Derived9,AnotherTemplate>::yes << std::endl;
    return 0;
    }
    #endif//CODE3
    ////////////////////////////////////////////////////////////////////////////////
    //该程序的运行结果如下:
    /*******************************************************************************
    Derived1 is kind of Template? 1
    Derived2 is kind of Template? 1
    Derived3 is kind of Template? 1
    Derived4 is kind of Template? 1
    Derived5 is kind of Template? 1
    Derived6 is kind of Template? 1
    Derived7 is kind of Template? 1
    Derived8 is kind of Template? 1
    Derived9 is kind of Template? 1
    Derived1 is kind of AnotherTemplate? 0
    Derived2 is kind of AnotherTemplate? 0
    Derived3 is kind of AnotherTemplate? 0
    Derived4 is kind of AnotherTemplate? 0
    Derived5 is kind of AnotherTemplate? 0
    Derived6 is kind of AnotherTemplate? 0
    Derived7 is kind of AnotherTemplate? 0
    Derived8 is kind of AnotherTemplate? 0
    Derived9 is kind of AnotherTemplate? 0
    *******************************************************************************/
    ////////////////////////////////////////////////////////////////////////////////
    #if 0

    从CODE3的运行结果可以看出:我们已经成功的实现了判断某个型别是否是某个模板类
    的派生类或者是直接实例化的类的能力。因此我们就可以在自己编写代码的时候利用这些
    功能来实现静态分派的能力。

    至于第三种方法已经在前面的章节中讨论过了。根据索引号访问scatter产生的代码的
    同类型变量的方法就是采用了第三种方法。

    到目前为止,已经讨论了我所知道的C++里面的类型识别的一般方法。具体如何应用就要
    看您的发挥了。我编写的撤销和重做库中就采用了这里的方法来识别简单类型和复合类型的。

    #endif

    发表于 @ 2006年04月24日 19:55:00|评论(loading...)|编辑

    新一篇: 撤销和重做(Undo和Redo)的C++完美实现(9) | 旧一篇: 撤销和重做(Undo和Redo)的C++完美实现(8-B)

    评论

    #mouse.cat 发表于2006-04-25 00:28:00  IP: 10.165.83.*
    我想辨别complex类型可以这样写

    template <typename T> struct traits<std::complex<T> >
    {
    static const char*name()
    {
    //简写
    return std::complex+struct traits<T>;
    }
    };

    不过vc6的编译器是不行的
    #pandaxcl 发表于2006-04-25 08:54:00  IP: 202.114.78.*
    谢谢mouse.cat的评论。其实你所说的问题就是将本文中讨论的各种方法结合起来使用的例子。但是我写这篇文档的目的是说明类型识别的基本方法的,所以在采用例子的时候特意将你所说的这种情况化简了,就成了本文中介绍的例子了:)
    #老迈 发表于2006-04-25 09:59:00  IP: 218.25.162.*
    熊春雷:你好!
    在论坛上看到了你发的帖子,特地到你的blog里看了一下,感觉非常不错,希望能和你交个朋友,共同研究技术,呵呵。
    请到论坛上收一下我发的短消息
    #mcs51a 发表于2006-04-25 10:40:00  IP: 58.33.229.*

    template<typename T>
    struct Traits
    {
    LPCTSTR getName()
    {return #T;}
    }
    来替代 template<> struct Traits<char/int/float> {}等
    一层template MICRO在mfc rtti中 使用了很多宏的手法,可以参考哦
    #pandaxcl 发表于2006-04-25 11:19:00  IP: 202.114.78.*
    谢谢mcs51a的评论。为了使的代码容易理解,我尽量的少用宏来写文档,但是作为一个库的话,就可能使用您所说的这种宏处理方式了。
    #pandaxcl 发表于2006-04-25 11:23:00  IP: 202.114.78.*
    谢谢mcs51a的评论。用typeid的话,得到的结果不同的编译器一般不相同,这里为了保证又统一的输出结果才不采用RTTI的
    #mcs51a 发表于2006-04-25 10:55:00  IP: 58.33.229.*
    ps: c++模板中类型信息也不是必需的,上面的例子typeid就可以了
    #肉骨头 发表于2006-04-28 11:09:00  IP: 221.122.38.*
    个人觉得还是从应用实例入手讲解,生动一些。
    直接从语法开始讲解,很是乏味。

    期待LZ的生动实例讲解。:)
    #pandaxcl 发表于2006-04-28 12:24:00  IP: 202.114.78.*
    感谢肉骨头的关注。在这里需要特别说明一下,这里的“ C++自动化(模板元)编程基础与应用”系列的文档都是为了“ 撤销和重做(Undo和Redo)的C++完美实现”系列文档而服务的,因为模板元编程的范围非常宽泛,从一个一个的具体例子讲的话,将会无穷无尽。所以这里介绍的模板元编程的语法的具体应用的例子在撤销和重做库中将会有非常具体的自动化应用,可以参看“撤销和重做(Undo和Redo)的C++完美实现”。写得还不是很好,但是随着时间的推移我会做得越来越好的。敬请关注:)
    #肉骨头 发表于2006-04-28 14:42:00  IP: 221.122.38.*
    可能是看老外的书看多了,比较喜欢 实例->分析->原理->应用 的学习模式了,呵呵。:P
    #pandaxcl 发表于2006-04-28 18:29:00  IP: 202.114.78.*
    再次谢谢肉骨头长期以来对我的博客的关注。需要解释一下,我现在是处于一个撤销和重做库的开发过程中,这都是我以前的构思,现在只是想尽可能的把我的设计思想表达出来,但是限于自己的文字表达能力,在短时间内可能很难有大幅度的提高。但是在撤销和重做库的开发基本完毕之后,我会重写这里的所有相关文档的,尽可能的做到容易使用、容易理解、容易扩展。敬请关注:)
    #jt 发表于2006-04-29 18:56:00  IP: 218.104.71.*
    pandaxcl挺热心的,赞一下,呵呵
    #tiredboy 发表于2006-09-09 09:50:00  IP: 202.104.245.*
    熊春雷兄弟,你好,我是uplinux.net的站长,之前敝站在Chinaitlab转载了兄弟的一篇文章《C++自动化(模板元)编程基础与应用》,由于当时Chinaitlab没有注明出处及作者,本站转载时也没有去详细考察出处,这是对兄弟的极其不尊重,在这里致以最深切的道歉,望兄弟见谅,现在本站已经加上了兄弟的大名和文章的出处了,请兄弟查证:http://www.uplinux.net/article/2006/0609/article_838.html
    再次对兄弟的支持表示感谢!
    #tiredboy 发表于2006-09-09 09:51:00  IP: 202.104.245.*
    熊春雷兄弟,你好,我是uplinux.net的站长,之前敝站在Chinaitlab转载了兄弟的一篇文章《C++自动化(模板元)编程基础与应用》,由于当时Chinaitlab没有注明出处及作者,本站转载时也没有去详细考察出处,这是对兄弟的极其不尊重,在这里致以最深切的道歉,望兄弟见谅,现在本站已经加上了兄弟的大名和文章的出处了,请兄弟查证:http://www.uplinux.net/article/2006/0609/article_838.html
    再次对兄弟的支持表示感谢!
    #tiredboy 发表于2006-09-09 09:51:00  IP: 202.104.245.*
    熊春雷兄弟,你好,我是uplinux.net的站长,之前敝站在Chinaitlab转载了兄弟的一篇文章《C++自动化(模板元)编程基础与应用》,由于当时Chinaitlab没有注明出处及作者,本站转载时也没有去详细考察出处,这是对兄弟的极其不尊重,在这里致以最深切的道歉,望兄弟见谅,现在本站已经加上了兄弟的大名和文章的出处了,请兄弟查证:http://www.uplinux.net/article/2006/0609/article_838.html
    再次对兄弟的支持表示感谢!
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © pandaxcl