[Insight-developers] Template function specialization

Williams, Norman K norman-k-williams at uiowa.edu
Tue Jan 18 13:51:42 EST 2011



On 1/18/11 12:01 PM, "antonin perrot-audet" <antonin07130 at gmail.com> wrote:

>Thanks a lot William, I implemented your solution and it works perfectly !

Glad to hear it.

>
>I will now try to pass a pointer to an image of fixed dimension to
>GenerateData, to avoid the construction of the dummy structure.

There's more penalty to what you suggest than what I did.  The dummy
structure pointer  is just there to tell the compiler which version of
GenerateData to call.  The structure itself has no members and occupies no
memory. You could do something like this:


template<class ImageType>
class TestOverLoad
{
public:
    void GenerateData();
private:
    // the general ND case -- template member function
    template<unsigned dim>
 void GenerateData(itk::Image<ImageType::PixelType,dim>  *);
    // the 2D special case -- non-template member function
    void GenerateData(itk::Image<ImageType::PixelType,2> *);
};


But the net result is the same -- the pointer parameter isn't ever used,
and can be of any type so long as it allows the compiler to pick the right
function to call at compile time.

The only overhead involved is that GenerateData without arguments doesn't
need a frame pointer, and with the dummy parameter, an extra 'push 0' is
added at the point of compilation. But a good compiler will optimize that
away, since the dummy parameter is never used.
 
>
>Yes indeed, I think I was trying to do partial template specialization
>of a member function, which seems to be forbidden in C++ ?
>
>thanks again,
>
>Cheers
>
>On 01/18/2011 06:32 PM, Williams, Norman K wrote:
>> The problem you're running into is that C++ is very touchy about
>>templates
>> and specialization. It's rather a confusing topic, about which books are
>> written.  The solution involves some form of Template Metaprogramming.
>>
>> Below is one solution to your problem, that I came up with off the top
>>of
>> my head. It uses member function overloading, and doesn't require
>>partial
>> template specialization, which is what I think you were trying to do.
>> There are other ways to do this, but this is the one that came
>>immediately
>> to mind:
>>
>> #include<iostream>
>> #include<itkImage.h>
>>
>> template<class ImageType>
>> class TestOverLoad
>> {
>> public:
>>    void GenerateData();
>> private:
>>    // dummy type to discriminate dimension at compile time
>>    template<unsigned dim>  struct DimType {};
>>    // the general ND case -- template member function
>>    template<unsigned dim>   void GenerateData(DimType<dim>  *);
>>    // the 2D special case -- non-template member function
>>    void GenerateData(DimType<2>  *);
>> };
>>
>> // The 2D special case
>> template<class ImageType>
>> void
>> TestOverLoad<ImageType>::
>> GenerateData(DimType<2>  *)
>> {
>>    std::cout<<  "TwoD case"<<  std::endl;
>> }
>>
>> // General Case ND
>> template<class ImageType>
>> template<unsigned dim>
>> void
>> TestOverLoad<ImageType>::
>> GenerateData(DimType<dim>  *)
>> {
>>    std::cout<<  "General Case, Dim ="
>>              <<  ImageType::ImageDimension
>>              <<  std::endl;
>> }
>>
>> template<class ImageType>
>> void
>> TestOverLoad<ImageType>::
>> GenerateData()
>> {
>>    // depending on dimension of ImageType, only one version of
>>    // GenerateData will actually be instantiated
>>    // The DimType<dim>  * parameter never used, but it's a low-cost way
>>    // to force compile-time type discrimination
>>    this->GenerateData(static_cast<  DimType<ImageType::ImageDimension>
>> *>(0));
>> }
>>
>> int
>> main(int argc, char **argv)
>> {
>>    TestOverLoad<itk::Image<unsigned char,2>  >  x2;
>>    x2.GenerateData();
>>
>>    TestOverLoad<itk::Image<unsigned char,3>  >  x3;
>>    x3.GenerateData();
>> }
>>
>



More information about the Insight-developers mailing list