plantilla de plantilla c++?
templates properties (4)
Me gustaría saber si podríamos hacer algo para extraer el tipo de clase de dos propiedades de punteros de función.
Realmente no. No hay forma de saber cuál es el tipo de clase de un puntero de miembro, incluso con características de tipo de metaprogramación.
Ah, y esos son punteros de miembro , no punteros de función. No son lo mismo.
Me las he arreglado para crear una clase de preperty con todo lo que esperamos de uno. Me refiero a cuando lo usas no necesitas llamar a funciones simplemente usando operator =
hará todo el trabajo. pero solo hay una cosa que creo que sería bueno si pudiéramos resolver:
template <class T, class X,void (T::*setFunc)(const X&),const X& (T::*getFunc)()const> class property
{
T* const owner;
X data;
friend T;
property(T*const pOwner) : owner (pOwner)
{
}
public:
property& operator = (const X& input){(owner->*setFunc)(input);return *this;}
operator const X&()const {return (owner->*getFunc)();}
};
struct c
{
protected:
void setInt(const int& data);
const int& getInt() const;
public:
c();
property<c, int ,&setInt,&getInt> myInt;
};
c::c() : myInt(this)
{
}
void c::setInt(const int& data)
{
myInt.data = data;
}
const int& c::getInt() const
{
return myInt.data;
}
ver propiedad de clase tiene 4 argumentos y el primer argumento es el tipo de clase en sí. Me gustaría saber si podríamos hacer algo para extraer el tipo de clase de dos propiedades de punteros de función. algo así como property <int, &setInt, &getInt> myInt;
.
¿Conoces alguna forma de eliminar el primer parámetro de plantilla?
Si desea omitir la especificación explícita de los parámetros de tipo, el siguiente código cumplirá con el propósito. Sin embargo, este código requiere VC2010.
template <class> struct class_type;
template <class C, class T> struct class_type< T(C::*) > { typedef C type; };
template <class> struct param_type;
template <class C, class T> struct param_type< void(C::*)(const T&) > {
typedef T type;
};
template <class S, S setFunc, class G, G getFunc> struct property {
typedef typename class_type<S>::type T;
typedef typename param_type<S>::type X;
T* const owner;
X data;
....
};
#define PROPERTY(set, get) property<decltype(&set), &set, decltype(&get), &get>
struct c {
void setInt(const int& data);
const int& getInt() const;
PROPERTY(setInt, getInt) myInt;
};
Por cierto, MSVC tiene su propia propiedad . Probablemente esto sea más fácil si cumple el propósito.
Si lo que necesita es eliminar los parámetros de la plantilla, puede hacerlo, pero no eliminando el primer parámetro de la plantilla. Lo que puede hacer es eliminar los parámetros de la plantilla del puntero del método, porque realmente no son necesarios. El siguiente código compilado con gcc sin problemas, es una versión simplificada de lo que necesita, pero puede ver lo que se puede hacer con él:
template<class T, class X> class Foo {
public:
typedef const X& (T::*GetterFunc)() const;
typedef void (T::*SetterFunc)(const X&);
Foo(T* instance, GetterFunc getter, SetterFunc setter):
_owner(instance), _getter(getter), _setter(setter) { }
T* _owner;
GetterFunc _getter;
SetterFunc _setter;
};
class FooBar {
};
class Bar {
public:
Bar(FooBar& foobar):_foobar(foobar) { }
const FooBar& get() const { return _foobar; }
void set(const FooBar& foobar) { _foobar = foobar; }
FooBar _foobar;
};
int main() {
FooBar foobar;
Bar bar(foobar);
Foo<Bar, FooBar> foo(&bar, &Bar::get, &Bar::set);
return 0;
}
¡Éxito por fin! http://ideone.com/XJ7of
Esta versión ligeramente mejor funciona solo en Comeau (no estoy seguro si Comeau o gcc son correctos, pero gcc se queja de la designación de friend
).
#include <iostream>
#include <typeinfo>
template <class T, class X,void (T::type::*setFunc)(const typename X::type&),const typename X::type& (T::type::*getFunc)()const> class property_impl
{
typename T::type* const owner;
friend typename T::type;
property_impl(typename T::type* const pOwner) : owner (pOwner)
{
}
public:
property_impl& operator = (const typename X::type& input){(owner->*setFunc)(input); return *this;}
operator const typename X::type&()const {return (owner->*getFunc)();}
};
template<typename T> struct identity { typedef T type; };
template<typename Arg, typename T>
identity<T> match_memfn_classtype( void (T::*fn)(Arg) );
template<typename Arg, typename T>
identity<Arg> match_memfn_argtype( void (T::*fn)(Arg) );
#define property(setter,getter) property_impl<decltype(match_memfn_classtype(setter)), decltype(match_memfn_argtype(setter)), setter, getter>
struct C
{
private:
int hiddenData;
protected:
void setInt(const int& data) { hiddenData = data; std::cout << "setter used/n"; }
const int& getInt() const { std::cout << "getter used/n"; return hiddenData; }
public:
C() : myInt(this), hiddenData(5) {}
property(&C::setInt,&C::getInt) myInt;
};
int main(void)
{
C c;
std::cout << "c.myInt = " << c.myInt << ''/n'';
c.myInt = -1;
std::cout << "c.myInt = " << c.myInt << ''/n'';
return 0;
}
Y VC ++ 2010 se ahoga en todas las variaciones, aunque funciona para el uso muy simple de match_memfn_classtype
.
Informe de error archivado (por favor, voto favorable):
Microsoft actualizó el informe de fallos para decir que han descubierto una solución.