Consider the following code
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
};
Look, it is possible to save any template parameter if this parameter is a typename or an integer value. The thing is that pointer to member is an offset, i.e. integer. Now I want to save any pointer to member in compile time:
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));
}
How to save pointer to member in compile time? I use VS2008.
Note. Compile time is critical. Please don't write run-time solution. I know it.
Why using a template?
The following compiles
mp
to this on gcc-4.4.1 (I don't have access to MSVC at the moment):It is just an offset to the member, which looks pretty compile-time to me.
With template, you need to specify the definition outside of the class:
Which compiles to:
However this all smacks of standard library features reimplementation (see
std::tr1::mem_fn
).It would be nice to have more elaborate explanation of why 'compile-time is important' (helps suggesting alternatives). But to my notion everything you need to be done compile time with pointer-to-member, you actually can do. My variant is Thomas's suggestion blended with some C++ philosophy of sort. First lets define:
this struct template can effectively serve as compile time value, and you don't need "static value = v;", to use it either at compile or run time. Consider:
and
Foo and Bar are functionally equivalent, every template meta-kadabra which can be done with Foo can also be done with Bar (just pass val instead of n). The same vay you can pack pointer to member into val<>:
these compile time values now can be stored in type lists (like boost::mpl::something), compared, transformed, etc., everything compile time. And when you will finally want to use them as pointer-to-member at run time, just define one function template:
and use it:
P.S.: there are some clumsy constructs about this solution, but it is all for sake of simplicity and explanation. For example rather ugly (a .* extract (a_i ())) may be simplified by wrapping it into something more pointer-to-member specific:
where mem_type is class template which extracts type of member referred by M. Then usage would be:
You can't initialize a static member inside the definition of a struct. It needs to be declared outside like this (which is probably not what you intended with the template, but anyway):
You can't.
But you can use a functionoid instead. This can be a compile-time solution. And because the compiler can inline things, it's possibly even faster than a pointer to a member function. Example:
Untested, but you get the idea.