tipos punteros puntero plantillas objeto estructuras curso clases c++ templates c++11 c++14 pointer-to-member

c++ - punteros - Puntero a miembro de clase como parámetro de plantilla



this-> en c++ (4)

Quiero usar un puntero a un miembro de la clase como un parámetro de plantilla como en:

template <class Class, class Result, Result Class::*Member> struct MyStruct { // ... };

El uso de esta estructura como MyStruct<SomeClass, SomeResult, &SomeClass::value> variable funciona bien, pero no me gusta que tenga que especificar SomeClass y SomeResult .

Me gustaría usar la MyStruct<&SomeClass::value> variable si es posible, pero sin perder la capacidad de pasar cualquier clase y tener cualquier tipo de resultado.

Intenté lo siguiente, pero la sintaxis es ilegal:

template <class Class, class Result> template <Result Class::*Member> struct MyStruct { // ... };

error: demasiadas plantillas-listas-parametros

Intenté usar una función auxiliar (que en realidad funciona en Clang pero GCC lo rechaza):

template <class Class, class Result> static constexpr auto makeMyStruct(Result Class::*member) -> MyStruct<Class, Result, member> { // ... }

error: uso del parámetro `miembro ''fuera del cuerpo de la función
error: el argumento de la plantilla 3 no es válido

¿Es posible tener un simple MyStruct<&SomeClass::value> , y si es así, cómo?

Pregunta relacionada que no resolvió mi pregunta:

  • Puntero a miembro de clase como parámetro de plantilla
  • Error de C ++ 0x con constexpr y función de plantilla de retorno

En c ++ 17, con la adición de auto en los argumentos de la plantilla ( P0127) , creo que ahora puede hacer:

template<auto value> struct MyStruct {}; template<typename Class, typename Result, Result Class::* value> struct MyStruct<value> { // add members using Class, Result, and value here using containing_type = Class; }; typename MyStruct<&Something::theotherthing>::containing_type x = Something();


En este documento se propuso una respuesta a mi pregunta para el próximo estándar de C ++:

Esta sintaxis fue propuesta:

template<using typename T, T t> struct some_struct { /* ... */ }; some_struct<&A::f> x;

La necesidad de una nueva construcción sintáctica indica que no se puede hacer eso ahora.

Espero que n3601 sea aceptado. :-)


Esto podría ser una solución en C ++ 11:

Puede definir los siguientes rasgos de tipo genérico:

template<class T> struct remove_member_pointer { typedef T type; }; template<class Parent, class T> struct remove_member_pointer<T Parent::*> { typedef T type; }; template<class T> struct baseof_member_pointer { typedef T type; }; template<class Parent, class T> struct baseof_member_pointer<T Parent::*> { typedef Parent type; };

Ahora puede definir una macro adicional de 4 líneas para cada estructura:

template<class Class, class Result, Result Class::*Member> struct _MyStruct { // ... }; #define MyStruct(MemberPtr) / _MyStruct<baseof_member_pointer<decltype(MemberPtr)>::type, / remove_member_pointer<decltype(MemberPtr)>::type, / MemberPtr>

... y utilízalo de la siguiente manera:

MyStruct(&SomeClass::value) myStruct; // <-- object of type MyStruct<&SomeClass:value>

Utilizo esto como una solución intermedia, hasta que cambiamos a C ++ 17.


Haz de tu clase de resultado un hijo de tu clase de plantilla. Suponiendo que el miembro puntero es un objeto de su clase de resultado en público o lo que sea, puede acceder a cualquier objeto haciendo algo como esto

template <stuff for this class> :: public result { blah }