Is there in C ++ 11 to get the type of a member pointer in a template?

I know this is not possible in C ++ 03, but I hope there are some new voodoo that would allow me to do this. See below:

template <class T> struct Binder { template<typename FT, FT T::*PtrTomember> void AddMatch(); }; struct TestType { int i; }; int main(int argc, char** argv) { Binder<TestType> b; b.AddMatch<int,&TestType::i>(); //I have to do this now b.AddMatch<&TestType::i>(); //I'd like to be able to do this (ie infer field type) } 

Is there a way to do this in C ++ 11? Does decltype help?

** UPDATE: Using Vlad's example I thought something like this would work (caveat: I did not compile since I am now creating a compiler with decltype support)

 template <class T> struct Binder { template<typename MP, FT ft = decltype(MP)> void AddMatch() { //static_assert to make sure MP is a member pointer of T } }; struct TestType { int i; }; int main() { Binder<TestType> b; b.AddMatch<&TestType::i>(); } 

Will this work?

+6
source share
4 answers

What you are trying to do cannot be done, i.e. you cannot use a member pointer as a constant expression unless you have a type. That is, the type of the template argument must be specified that is different from the type, or, in other words, there is no type for the template arguments.

+3
source

How about this (how the kicker works in C ++ 03):

 #include <iostream> #include <typeinfo> template< typename T > struct ExtractMemberTypeHelper; template< typename R, typename T > struct ExtractMemberTypeHelper< R(T::*) > { typedef R Type; typedef T ParentType; }; template< typename T > struct ExtractMemberType : public ExtractMemberTypeHelper< T > {}; struct foo { int bar; template< typename T > void func( const T& a_Arg ) { std::cout << typeid( typename ExtractMemberType< T >::Type ).name( ) << " " << typeid( typename ExtractMemberType< T >::ParentType ).name( ) << std::endl; } }; int main() { foo inst; inst.func( &foo::bar ); } 
+2
source

You can make a "T" to provide this information.

 template <class ...T> struct BoundTypes { }; template <class U, class T> struct BinderDecls { void AddMatch(); }; template <class U, class T, class ...Ts> struct BinderDecls<U, BoundTypes<T, Ts...>> :BinderDecls<U, BoundTypes<Ts...>> { using BinderDecls<U, BoundTypes<Ts...>>::AddMatch; template<TU::*PtrTomember> void AddMatch(); }; template <class T> struct Binder : BinderDecls<T, typename T::bound_types> { } 

Then it becomes easy

 struct TestType { typedef BoundTypes<int, float> bound_types; int i; float j; }; int main(int argc, char** argv) { Binder<TestType> b; b.AddMatch<&TestType::i>(); b.AddMatch<&TestType::j>(); } 

Alternatively, you can use friend function definitions

 template <class ...T> struct BoundTypes { }; template <class U, class T> struct BinderDecls { template<TU::*ptr> friend void addMatch(BinderDecl &u) { // ... } }; template <class U, class ...Ts> struct BinderDecls<U, BoundTypes<Ts...>> : BinderDecls<U, Ts>... { }; template<typename = void> void addMatch() = delete; template <class T> struct Binder : BinderDecls<T, typename T::bound_types> { } 

Then you can write

 struct TestType { typedef BoundTypes<int, float> bound_types; int i; float j; }; int main(int argc, char** argv) { Binder<TestType> b; addMatch<&TestType::i>(b); addMatch<&TestType::j>(b); } 
+2
source
 template <class T> struct Binder { template<typename FT> void AddMatch(); }; struct TestType { int i; }; int main() { Binder<TestType> b; b.AddMatch<decltype(&TestType::i)>(); } 
0
source

Source: https://habr.com/ru/post/916030/


All Articles