Compile time polymorphism for data members

The following initialize() code shows a method based on compile-time polymorphism. The compiled version of initialize() depends on int2type<true> and int2type<false> , only one of which will be true for the given template parameter T

It so happened that the data element T* m_datum; will work for both int2type<true> and int2type<false> .

Now I want to change the version of int2type<false> to std::vector<T> m_datum; , so my question is: how do I change my code so that the m_datum data member is polymorphic to int2type<> ?

Note: please ignore the code justification below - instead, I would like to focus on the mechanics of achieving compile time polymorphism for data members.

 #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 solution based on Nawaz recommendations

 #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; } 
+7
source share
2 answers

C ++ 11 Solution

Use std :: conditional as:

 #include <type_traits> template<class T> class Foo { //some info we can use throughout the class static const bool what = is_trivially_copyable<T>::value; typedef typename std::conditional<what, T*, std::vector<T>>::type data_type; //data members data_type m_data; //this is what you need! } 

Solution C ++ 03

You can write metafunction and partially specialize in this as follows:

 template<class T> class Foo { //primary template template<bool b, typename T> struct get { typedef T* type; }; //partial specialization template<typename T> struct get<false, T> { typedef std::vector<T> type; }; //some info we can use throughout the class static const bool what = is_trivially_copyable<T>::value; typedef typename get<what, T>::type data_type; //data members data_type m_data; //this is what you need! }; 

Therefore, when what is true , data_type will be T* , otherwise it will be std::vector<T> if required.

In any case, you do not need an int2type class int2type . Just remove this from your code. You can write cleaner code without it.

+8
source

What about:

 // Generic template <typename T, typename Arg> struct datum_type_dispatch {}; // Specialization for Arg = int2type<true> template <typename T> struct datum_type_dispatch<T, int2type<true> > { typedef T* type; }; // Specialization for Arg = int2type<false> template <typename T> struct datum_type_dispatch<T, int2type<false> > { typedef std::vector<T> type; }; template <typename T> class Foo { // ... private: // Get the datum type based on int2type<...> typedef typename datum_type_dispatch<T, int2type<is_trivially_copyable<T>::value> >::type datum_type; datum_type m_datum; }; 
+5
source

All Articles