如何在编译时保存指向成员的指针?

Ale*_*tov 6 c++ templates pointer-to-member

请考虑以下代码

template<typename T, int N>
struct A {
  typedef T value_type; // OK. save T to value_type
  static const int size = N; // OK. save N to size
};
Run Code Online (Sandbox Code Playgroud)

看,如果此参数是typename或整数值,则可以保存任何模板参数.问题是指向成员的指针是一个偏移量,即整数.现在我想在编译时保存任何指向成员的指针:

struct Foo {
   int m; 
   int r;
};

template<int Foo::*ptr_to_member>
struct B {
   // Next statement DOES NOT WORK!
   static int Foo::* const saved_ptr_to_member = ptr_to_member; 
};

// Example of using
int main() {
    typedef B<&Foo::m> Bm;
    typedef B<&Foo::r> Br;
    Foo foo;
    std::cout << (foo.*(Bm::saved_ptr_to_member));
}
Run Code Online (Sandbox Code Playgroud)

如何在编译时保存指向成员的指针?我用的是VS2008.

注意.编译时间至关重要.请不要编写运行时解决方案.我知道.

Ale*_*x B 1

为什么使用模板?

#include <cstdio>

struct Foo {
    int a;
    int b;
} foo = {2, 3};

int const (Foo::*mp) = &Foo::b;

int
main() {
    printf("%d\n", foo.*mp);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

以下内容mp在 gcc-4.4.1 上编译为此内容(我目前无法访问 MSVC):

.globl mp
        .align 4
        .type   mp, @object
        .size   mp, 4
mp:
        .long   4
Run Code Online (Sandbox Code Playgroud)

它只是成员的偏移量,对我来说看起来相当编译时。

使用模板,您需要在类外部指定定义:

#include <cstdio>

struct Foo {
   int m;
   int r;
} foo = {2, 3};

template<int Foo::*Mem>
struct B {
   static int Foo::* const mp;
};

template<int Foo::*Mem>
int Foo::* const B<Mem>::mp = Mem;

int main() {
    typedef B<&Foo::m> Bm;
    typedef B<&Foo::r> Br;
    printf("%d, %d\n", foo.*(Bm::mp), foo.*(Br::mp));
}
Run Code Online (Sandbox Code Playgroud)

编译为:

g++ -O2 -S -o- b.cc | c++filt

...

        .weak   B<&(Foo::r)>::mp
        .section        .rodata._ZN1BIXadL_ZN3Foo1rEEEE2mpE,"aG",@progbits,B<&(Foo::r)>::mp,comdat
        .align 4
        .type   B<&(Foo::r)>::mp, @object
        .size   B<&(Foo::r)>::mp, 4
B<&(Foo::r)>::mp:
        .long   4
        .weak   B<&(Foo::m)>::mp
        .section        .rodata._ZN1BIXadL_ZN3Foo1mEEEE2mpE,"aG",@progbits,B<&(Foo::m)>::mp,comdat
        .align 4
        .type   B<&(Foo::m)>::mp, @object
        .size   B<&(Foo::m)>::mp, 4
B<&(Foo::m)>::mp:
        .zero   4
Run Code Online (Sandbox Code Playgroud)

然而,这一切都带有标准库功能重新实现的味道(请参阅 参考资料std::tr1::mem_fn)。