• [百度空间] [note] pointer to member is a POD type


    C++03 3.9-10:

    1

    Arithmetic types (3.9.1), enumeration types, pointer types, and pointer to member types (3.9.2), and cv-qualified versions of these types (3.9.3) are collectively called scalar types. Scalar types, POD-struct types, POD-union types (clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called POD types.

     

    As we all knows the pointer to member may not be cast into void* (GCC is OK but it's a special case anyway), according to the standrad we can store the pointer to member to a char buffer though. Unfortunately, the size of "pointer to member" is implementation defined, so we still need some hack for different compilers.

    here's a table for sizeof(pointer to member) for some compilers 

    (http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Compiler            Options     Single  Multi   Virtual Unknown
        MSVC                        4       8       12      16
        MSVC            /vmg        16#     16#     16#     16
        MSVC            /vmg /vmm   8#      8#      --      8
        Intel_IA32                  4       8       12      16
        Intel_IA32      /vmg /vmm   4       8       --      8
        Intel_Itanium               8       12      16      20
        G++                         8       8       8       8
        Comeau                      8       8       8       8
        DMC                         4       4       4       4
        BCC32                       12      12      12      12
        BCC32           /Vmd        4       8       12      12
        WCL386                      12      12      12      12
        CodeWarrior                 12      12      12      12
        XLC                         20      20      20      20
        DMC small                   2       2       2       2
        medium                      4       4       4       4
        WCL small                   6       6       6       6
        compact                     6       6       6       6
        medium                      8       8       8       8
        large                       8       8       8       8

    the original article implement each compiler's pointer to member mechanism, which I believe is insane, it's definitely not a good way to write portable codes.here's what I'm doing (code snippet).

    所以pointer to member 可以被保存在byte array 里面再被解出来.这对于做delegate很有帮助.这是我目前使用的方法.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    class Delegate
    {
    public:
    //per-compiler constant, or use a max enough size for all compilers
    #if COMPILER == COMPILER_MSVC
        static const size_t MAX_POINTER2MEMBER_SIZE = 16;
    #elif COMPILER == COMPILER_GNUC
        static const size_t MAX_POINTER2MEMBER_SIZE = 8;
    #else
        static const size_t MAX_POINTER2MEMBER_SIZE = 20;
    #endif
     
        void* mPtr;
        char  mMemberRaw[MAX_POINTER2MEMBER_SIZE ];
     
        //store the pointer to member to a byte buffer
        template <typename T>
        explicit Delegate(T* ptr, void (T::*func)(void*) )
        {
            assertsizeof(func) <= MAX_SIZE );
            ::memset(mMemberRaw, 0, MAX_SIZE);
            ::memcpy(mMemberRaw, &func, sizeof(func) );
        }
    };
     
     
    //invoke function: extract the "pointer to member" from the byte buffer
    {
        ...
        typedef void (T::*TMemberFn)(void*);
        TMemberFn TFn = NULL;
        ::memcpy(&TFn, mMemberRaw, sizeof(TFn) );
        ( ((T*)mPtr)->*TFn )( data);
    }

    there's a very efficient way to do the delegate :

    http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates

    他也是用模板函数,但不同的是把函数地址作为模板参数.本来打算改用这个方法的.但是唯一的缺点就是需要显式指定模板参数<>来实例化, 而构造函数只能通过TAD来套用模板参数,不能显式指定...所以他用的是一个静态模板函数来构造一个对象

    1
    delegate d = delegate::frommember<T,&T::func>( pOjb); //这样稍微有点恶心.

    而我使用的方式虽然多了一个char[], 有一点点额外的内存开销和运行时开销,但是大多数情况下几乎可以忽略不计.

    主要是可以通过Template Arugment Deduction 直接创建delegate, 比如:

    1
    Delegate d(pObj, &CLASS::function);

    所以考虑了一下,决定暂时不用他的那种方法(用起来稍微不方便,但是效率非常高).以后看情况再考虑要不要改.

    另外,作为一个C++程序猿, 个人觉得"数据绑定", "反射","代理",这些使用时尽量谨慎, 不可滥用. 除了在event/msg 和 UI/Tools的极少数地方要用以外,其他地方还是尽量不要用为好. 最近把数据绑定框架做了简单重构, 幸好用到的地方不多(主要是编辑器在用), 要不然重构就哭了. 目前还没有反射,暂时不需要, 以后需要时再加.最好是另外封装,不影响现在的代码.

  • 相关阅读:
    一文搞定 Spring Boot & Shiro 实战
    CPU 到底是怎么认识代码的?涨姿势了!
    Java 可重入锁内存可见性分析
    大牛总结的 Git 使用技巧,写得太好了!
    厉害了,如何搭建一套自己的私有网盘?
    深入浅出 Java 中 JVM 内存管理
    SLA服务可用性4个9是什么意思?怎么达到?
    解决springboot配置@ControllerAdvice不能捕获NoHandlerFoundException问题
    mybatis多参数使用方法且其中有的参数是多个值使用in查询
    Optional导致的 java.util.NoSuchElementException: No value present
  • 原文地址:https://www.cnblogs.com/crazii/p/4512781.html
Copyright © 2020-2023  润新知