Is there a pointer to member traits or something like that?

Based on my other question .

Consider the following code

template<typename T, int N> struct A { typedef T value_type; // save T to value_type static const int size = N; // save N to size }; 

Look, I can use value_type and size as a template parameter.

 typedef A<int, 2> A1; typedef A<A1::value_type, A1::size + 3> A2; // OK, A2 is A<int,5> 

Now I want to do the same with a member pointer:

 struct Foo { int m; int r; }; template<int Foo::*Mem> struct B { static int Foo::* const mp; }; template<int Foo::*Mem> int Foo::* const B<Mem>::mp = Mem; // Save pointer to member 

But I get an error.

 typedef B<&Foo::m> B1; typedef B<B1::mp> B2; // DOES NOT WORK 

How to make the last line work? Or how to get a simulation result?

Note. I know this is not working. No references to the C ++ standard are required. I need a workaround.

+5
c ++ templates pointer-to-member
source share
4 answers

It should not work in accordance with the C ++ 5.19 / 2 standard:

Other expressions are considered constant expressions only for the purpose of non-stationary initialization of a static object (3.6.2). Such constant expressions must be evaluated by one of the following:
- value of the null pointer (4.10),
- value of the pointer of the zero element (4.11),
- arithmetic constant expression,
- constant expression of the address,
- link constant,
- expression of the address constant for the full type of the object, plus or minus the integral constant expression,
or
- pointer to the expression of the constant of the participant .

This is not the answer to the original question, but it is the answer to this incorrect operator.

+1
source share

Mike is right that he should compile. This is a bug in VS.

0
source share

Not quite the answer, but does accessing Mem really work?

i.e.: B1 :: Mem instead of B1 :: mp.

I am sure that the standard does not allow this, since we usually name the template name typedef when it is type, instead of accessing it directly, but technically it may possibly allow it (not sure what this will imply). If your solution probably doesn't work because it requires initialization of a static member that executes at runtime (correct me if I am wrong), so it cannot be obtained at compile time as you want.

Perhaps you could try to give us a more complete picture of what you are trying to do with your trait / policy class to find out if a workaround is possible.

0
source share

I was surprised to find that this does not happen. At least in the expected places, for example:

Nothing here http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/index.html not here http://en.cppreference.com/w/cpp/types/is_member_pointer

Based on this http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html and http://en.cppreference.com/w/cpp/types / is_member_pointer it’s easy to collapse your own.

 #include<type_traits> // std::is_pointer_member template<class MP> struct member_pointer_traits_helper; template< class T, class U > struct member_pointer_traits_helper<TU::*>{ using class_type = U; using declaration_type = T; }; template< class MP > struct member_pointer_traits : member_pointer_traits_helper<typename std::remove_cv<MP>::type> {}; struct B{ int b; }; int main(){ using std::same; static_assert(std::is_member_pointer<int B::*>::value == true, ""); static_assert(is_same<member_pointer_traits<int B::*>::class_type, B>{}, ""); static_assert(is_same<member_pointer_traits<int B::*>::declaration_type, int>{}, ""); static_assert(is_same<member_pointer_traits<decltype(&B::b)>::declaration_type, int>{}, ""); // static_assert(is_same<member_pointer_traits<double>::class_type, B>{}, ""); // error } 

I'm not sure the names are optimal. Also, when applied to a non-member pointer, this will give a compiler error (this project will be copied from http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits .html ), another alternative might be to return void (which is obviously a failure, since void cannot be a class or an element type.)

(with some minor modifications, it can be used with C ++ 98, C ++ 11 is used to make it more understandable.)

0
source share

All Articles