In the following code, initialize() illustrates a method based on compile-time polymorphism. The version of initialize() compiled depends on int2type<true> and int2type<false>, only one of which will be true for a given template parameter T.
It just so happens that data member T* m_datum; will work for both int2type<true> and int2type<false>.
Now, I want to change the int2type<false> version to std::vector<T> m_datum;, so my question is, how do I modify my code so that the data member m_datum is polymorphic on int2type<>?
Note: please ignore the rationale behind the code 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’s 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;
}
C++11 Solution
Use std::conditional as:
C++03 Solution
You can write a metafunction and partially specialize this as follows:
So when
whatistrue,data_typewill turn out to beT*, or else it will bestd::vector<T>, as desired.In either case, you don’t need
int2typeclass template. Just remove that from your code. You can write cleaner code, without it.