On Thursday, 12 December 2013 at 14:55:28 UTC, Craig Dillabaugh
wrote:
I am not sure if this belongs in D.learn, but it might be of
interest. I was writing some C++ code for a project at work
and have a class that stores image data from a file. The image
data can be in just about any numeric (int/float/complex) type,
so I wanted a 'wrapper' class/struct that could hold any type
of data without being 'parameterized' (we use templates for
image access).
My class contains a union ( called 'data') with every possible
type of pointer and parameter for indicating the data type.
However, at some point code eventually needs to get at the
data, so I have the following beauty of a template method,
(calling the image structure RAWImageDataStore was a bad design
decision on my part, need to change that soon, its very
Java-esque):
template class T
RAWImageDataStoreT* getBandData( )
{
T t;
//Check struct data type vs template type.
if( datatype == TYPE_8u typeid(t) == typeid(uint8_t) ) {
return reinterpret_cast RAWImageDataStoreT* (
data.t8u );
}
else if ( datatype == TYPE_16s typeid(t) ==
typeid(int16_t) ) {
return reinterpret_cast RAWImageDataStoreT* (
data.t16s );
}
//a number of types left out, I am sure you get the idea.
//but you need to see the complex types, they are beautiful.
else if ( datatype == TYPE_C16s
typeid(t) == typeid(std::complexint16_t) )
{
return reinterpret_cast RAWImageDataStoreT* (
data.tC16s );
}
\\OK, you only really needed to see one of the complex types
:o)
else if( datatype == TYPE_UNKNOWN ) {
std::cerr Cannot access band with unknown data type.
std::endl;
return 0;
} //+ a bit more error handling code.
Initially this didn't compile because I was missing the
reinterpret_cast statements. They effectively do nothing. If
the template type is int8_t then I return the data.t8u pointer,
which is a RAWImageDataStoreint8_t*, but have to cast it to
RAWImageDataStoreint8_t*. I must do this because when I call
the method type int16_t my return data.t8u returns the wrong
type of pointer for the method, even though I know that if the
type is int16_t this statement can never be reached.
I know there was some debate in the C++ community about whether
they should adopt D-like static if, which would have solved
this problem, since it would compile the illegal code right out
of existence.
Maybe there is a better way to do this in C++, but I thought I
would post here as a case-study in the usefulness of 'static
if'.
Craig
In C++ you can use partial specialization to achieve what you
want.
class Storage
{
public:
union {
float* fdata;
int* idata;
} data;
};
templatetypename T
T* get(Storage stor)
{
return 0; //or throw exception
}
template
float* getfloat(Storage stor)
{
return stor.data.fdata;
}
template
int* getint(Storage stor)
{
return stor.data.idata;
}
int main()
{
Storage stor;
float* fdata = getfloat(stor);
return 0;
}