A good advertisement for 'static if'

2013-12-12 Thread Craig Dillabaugh
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


Re: A good advertisement for 'static if'

2013-12-12 Thread FreeSlave
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;
}


Re: A good advertisement for 'static if'

2013-12-12 Thread FreeSlave
With some improvements you also can provide compile-time error 
about instantiation of non-specialized function (i.e. which has T 
as parameter), but I'm not sure what's good way to do it in C++.


Re: A good advertisement for 'static if'

2013-12-12 Thread Craig Dillabaugh

On Thursday, 12 December 2013 at 17:34:13 UTC, FreeSlave wrote:
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).



clip


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;
}


Thanks for this suggestion, it avoids the reinterpret cast 
nicely.  I've used template specialization in other cases, but it 
didn't occur to me in this case (plus adding the 
'reinterpret_cast' required less refactoring on my part at the 
time). However, I may switch my code to use this method since the 
resulting executable should be smaller/faster since the big if 
... else statement isn't inserted with every template 
instantiation.


However neither solution is as nice as 'static if' in D.  The 
benefits of having all my type checks in one space, and the 
'dead' code is eliminated in the instantiations.


Cheers, Craig