I want to have a template function like this:

template <class T>
void CreateBlankPatch(typename T::Pointer patch, unsigned int sideLength)
{
  CreateConstantPatch(patch, typename T::PixelType::Zero(), sideLength);
}

It works fine as long as Zero() is defined for the class T. However, with POD types, this is clearly not the case. So I want an unsigned char version of the template, I tried to do this:

template <>
void CreateBlankPatch<unsigned char>(typename T::Pointer patch, unsigned int sideLength)
{
  CreateConstantPatch(patch, 0, sideLength);
}

but it complained that T is not defined. I tried this (even though every example I've seen has empty <> for specializations):

template <class T>
void CreateBlankPatch<unsigned char>(typename T::Pointer patch, unsigned int sideLength)
{
  CreateConstantPatch(patch, 0, sideLength);
}

and I get

error: template-id ‘CreateBlankPatch<unsigned char>’ in declaration of primary template

Anyone know how to do this?

Thanks,

David

Recommended Answers

All 3 Replies

I figured it out:

template <>
void CreateBlankPatch<UnsignedCharImageType>(UnsignedCharImageType::Pointer patch, unsigned int sideLength)
{
  CreateConstantPatch<UnsignedCharImageType>(patch, 0, sideLength);
}

How silly of me. I need a "fake post" button. No matter how long I look at something, I figure it out 4 seconds after posting a question about it.

Sorry for the noise.

David

Hey David! I know you solved it, but if you want a more generic solution, I can suggest something. This case is a very good example of when traits can be very useful.

Consider this:

//define a type trait for images:
template <class T>
struct image_trait {
  typedef typename T::Pointer Pointer;
  struct PixelType {
    typedef typename T::PixelType::Type Type;
    static T::PixelType::Type Zero() { return T::PixelType::Zero(); };
  };
};

//specialize the trait for a primitive image (like unsigned char*)
template <>
struct image_trait<unsigned char*> {
  typedef unsigned char** Pointer;
  struct PixelType {
    typedef char Type;
    static char Zero() { return 0; };
  };
};

//then, you can have one function template that will work for all image types that have an appropriate image_trait (either the generic one or a specialization)
template <class T>
void CreateBlankPatch(typename image_trait<T>::Pointer patch, unsigned int sideLength)
{
  CreateConstantPatch(patch, typename image_trait<T>::PixelType::Zero(), sideLength);
}

This is how STL implements a lot of things. Like for iterators, all the STL algorithms can also work for pointer instead because, internally, they always go through a iterator_trait template to know the value type, reference type, etc., and a few specialization for pointers (like T*) make the STL algorithms compatible with them (or any other custom iterator you could come up with, as long as you provide a valid iterator_trait for it).

commented: Short simple post on Traits: Thx +4

Thanks Mike. I was actually just reading about traits the other day. That is clearly the right solution here.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.