En el siguiente código, initialize()
ilustra un método basado en el polimorfismo en tiempo de compilación. La versión de initialize()
compilada depende de int2type<true>
y int2type<false>
, de las cuales solo una será cierta para un parámetro de plantilla dado T
.Polimorfismo en tiempo de compilación para los miembros de datos
Sucede que el miembro de datos T* m_datum;
funcionará tanto para int2type<true>
como para int2type<false>
.
Ahora, yo quiero cambiar la versión int2type<false>
a std::vector<T> m_datum;
, así que mi pregunta es, ¿Cómo modificar mi código para que el miembro de datos m_datum
es polimórfico en int2type<>
?
Nota: ignore el razonamiento detrás del código a continuación - en su lugar, me gustaría centrarme en la mecánica de lograr el polimorfismo en tiempo de compilación para los miembros de los datos.
#include <type_traits>
#include <stdlib.h>
using namespace std;
template <bool n>
struct int2type
{
enum { value = n };
};
template< typename T >
struct is_trivially_copyable
{
static const bool value = std::is_standard_layout<T>::value;
};
template<class T>
class Foo
{
public:
Foo(size_t n) : m_nr(n)
{
initialize(int2type<is_trivially_copyable<T>::value>());
}
~Foo() { }
private:
void initialize(int2type<true>)
{
m_datum = (T*) calloc(sizeof(T), m_nr);
}
void initialize(int2type<false>)
{
m_datum = new T[m_nr];
}
private:
size_t m_nr;
T* m_datum; // ok for int2type<true>
// vector<T> m_datum; // want to change to this for int2type<false>
};
class Bar
{
public:
Bar() { }
virtual ~Bar() { }
};
int main(int argc, char** argv)
{
Foo<int> foo_trivial( 5);
Foo<Bar> foo_nontrivial(10);
return 0;
}
C++ 11 solución, basada en las recomendaciones de Nawaz
#include <type_traits>
#include <vector>
#include <stdlib.h>
using namespace std;
template< typename T >
struct is_trivially_copyable
{
static const bool value = std::is_standard_layout<T>::value;
};
template<class T>
class Foo
{
private:
static const bool what = is_trivially_copyable<T>::value;
typedef typename std::conditional<what,T*,std::vector<T>>::type type;
public:
Foo(size_t n) : m_nr(n)
{
initialize(m_datum);
}
~Foo() { }
private:
void initialize(T* dummy)
{
m_datum = (T*) calloc(sizeof(T), m_nr);
}
void initialize(std::vector<T>& dummy)
{
m_datum.resize(m_nr);
}
private:
size_t m_nr;
type m_datum;
};
class Bar
{
public:
Bar() { }
virtual ~Bar() { }
};
int main(int argc, char** argv)
{
Foo<int> foo_trivial( 5);
Foo<Bar> foo_nontrivial(10);
return 0;
}
es más convencional usar 'type' en lugar de' data_type' – Abyx
@Abyx: Sí. Estoy de acuerdo y editado. :-) – Nawaz
+1: Ya se conoce la biblioteca estándar del próximo estándar, más para fomentar el código del limpiador al eludir el desvío 'int2type <>' del OP. –