When trying to pass a template parameter to another template, I am getting an 'invalid template parameter' error. I even tried to force it with 'typename' with no success. Can anyone see what's wrong with this?

#include <itkImage.h>
#include <itkImageFileWriter.h>
#include <itkRescaleIntensityImageFilter.h>

template <class T>
void WriteImage(typename T::Pointer image, std::string filename);

int main(int, char *[])
{
  itk::Image<unsigned char, 2>::Pointer image = itk::Image<unsigned char, 2>::New();
  WriteImage<itk::Image<unsigned char, 2> > (image, "test.jpg");

  return EXIT_SUCCESS;
}

template <class T>
void WriteImage(typename T::Pointer image, std::string filename)
{
  typedef itk::RescaleIntensityImageFilter<typename T, typename T> RescaleFilterType; //template argument 1 is invalid
  //typedef itk::RescaleIntensityImageFilter<T, T> RescaleFilterType; // expected ';' before rescaleFilter

  RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();

}

Thanks,

David

Recommended Answers

All 18 Replies

what is the definition of
itk::RescaleIntensityImageFilter<typename T, typename T> ?
Are you sure you can pass two parameters of the same type to this template?

Do you have access to the definition of the itk::RescaleIntensityImageFilter template? Are you sure it takes 2 template arguments?

EDIT:
Oops, a little slow... Don't you hate it when you get sidetracked?

Yep, it takes two template parameters:

http://www.itk.org/Doxygen/html/classitk_1_1RescaleIntensityImageFilter.html

This compiles no problem:

template <class T>
void WriteImage(typename T::Pointer image, std::string filename)
{
  //typedef itk::RescaleIntensityImageFilter<typename T, typename T> RescaleFilterType; //template argument 1 is invalid
  //typedef itk::RescaleIntensityImageFilter<T, T> RescaleFilterType; // expected ';' before rescaleFilter

  typedef itk::RescaleIntensityImageFilter< itk::Image<unsigned char, 2> ,  itk::Image<unsigned char, 2> > RescaleFilterType;
  RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();

}

I'm concerned that the way you declared image is part of the problem. I think you may be trying to come through a "back door" that is tightly locked.

What happens if you change your prototype/definition to:

template <class T>
void WriteImage(T image, std::string filename);

and your call to:

WriteImage (image, "test.jpg");

???

In other words, you leave out the "extra" template argument and the "::Pointer" part...

The problem is that the image is type

itk::Image<unsigned char, 2>::Pointer

but the template paramters for the RescaleIntensityImageFilter need to be just

itk::Image<unsigned char, 2>

I got some help here the other day with a similar problem - the solution was that the ::Pointer was a "non-deducible context" and that's why I had to add the template parameter in the call:

WriteImage< itk::Image<unsigned char, 2> > (image, "test.jpg");

rather than just:

WriteImage(image, "test.jpg");

Any other ideas? These things are very frustrating sometimes...

Yeah, it's the types that concern me.

It's probably just a personal style thing, but I don't like that you are breaking up the datatype of the parameter into 2 parts (1 in the call/template arg and 1 in the actual template definition). Maybe try something like this:

template <class T>
void WriteImage(T image, std::string filename);  //prototype

WriteImage<itk::Image<unsigned char, 2>::Pointer > (image, "test.jpg"); //call

Notice where I moved the "::Pointer" part to... I suspect this is more what was meant in that other thread.

That would work fine if all I needed to do was use 'image' inside the function. The problem is that I have instantiate this other class, RescaleIntensityImageFilter, using the type WITHOUT the ::Pointer

typedef itk::RescaleIntensityImageFilter< itk::Image<unsigned char, 2> ,  itk::Image<unsigned char, 2> > RescaleFilterType;

Is there a way to do that with the method you've suggested?

No, that code is not an instantiatition, it's a typedef. This is how you actually defined it, based on your OP:

typedef itk::RescaleIntensityImageFilter<typename T, typename T> RescaleFilterType;

The actual type generated by the typedef, and thus instantiated, depends on the template argument you supply when you call WriteImage.
Are you sure that your actual instantiation later on doesn't need the Pointer part? Have you tried it?

Yes, I'm sure.

This works

itk::RescaleIntensityImageFilter<itk::Image<unsigned char, 2> ,   
    itk::Image<unsigned char, 2> >::Pointer RescaleFilterType =
    itk::RescaleIntensityImageFilter<itk::Image<unsigned char, 2> ,   
    itk::Image<unsigned char, 2> >::New();

and this doesn't

itk::RescaleIntensityImageFilter<itk::Image<unsigned char, 2>::Pointer , 
  itk::Image<unsigned char, 2>::Pointer >::Pointer RescaleFilterType =
  itk::RescaleIntensityImageFilter<itk::Image<unsigned char, 2>::Pointer , 
  itk::Image<unsigned char, 2>::Pointer >::New();

(now you see why I use typedefs? hehe)

template <class T>
void WriteImage(typename T::Pointer image, std::string filename);

As per the IS, a nested typename (for example, the typename Pointer nested in the typename T here) is non-deducible.

If a template parameter is used only in nondeduced contexts and is not explicitly specified, template argument deduction fails.

The nondeduced contexts are:

* The nested-name-specifier of a type that was specified using a qualified-id.

* A type that is a template-id in which ... <elided>

Right, so that non-deducibility can be resolved by simply placing T in the angle brackets before the parameter list in the function call:

function<T>(params)

The problem here seems to be re-using the template parameter as the parameter for another template for some reason?

Yeah, template typedefs are nice when they work. I'm not saying that you shouldn't use them. But, they are a pain if they don't work.

Are these "Pointer" objects actually pointers? Can you dereference them? I'm wondering if a reference wouldn't be helpful, at least temporarily, to cut down on the amount of template syntax floating around.

Maybe something like this:

#include <itkImage.h>
#include <itkImageFileWriter.h>
#include <itkRescaleIntensityImageFilter.h>

template <class T>
void WriteImage(typename T &image, std::string filename);

int main(int, char *[])
{
  itk::Image<unsigned char, 2>::Pointer image = itk::Image<unsigned char, 2>::New();
  WriteImage(*(image), "test.jpg");

  return EXIT_SUCCESS;
}

template <class T>
void WriteImage(typename T &image, std::string filename)
{
  typedef itk::RescaleIntensityImageFilter<typename T, typename T> RescaleFilterType; //template argument 1 is invalid
  //typedef itk::RescaleIntensityImageFilter<T, T> RescaleFilterType; // expected ';' before rescaleFilter

  RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New();

}

EDIT:
Another thing that comes to mind. Is "itk" an actual class or a namespace? As I'm sure you've gathered, I know nothing about this package. I'm just trying to help with syntax...

They are smart pointers.

But the classes all have:

Image(const Self &);          //purposely not implemented

So I get:

error: ‘itk::Image<TPixel, VImageDimension>::Image(const itk::Image<TPixel, VImageDimension>&) [with TPixel = unsigned char, unsigned int VImageDimension = 2u]’ is private

when I do this:

#include <itkImage.h>
#include <itkImageFileWriter.h>
#include <itkRescaleIntensityImageFilter.h>

template <class T>
void WriteImage(T image, std::string filename);

int main(int, char *[])
{
  itk::Image<unsigned char, 2>::Pointer image = itk::Image<unsigned char, 2>::New();
  WriteImage<itk::Image<unsigned char, 2> >(*(image), "test.jpg");

  return EXIT_SUCCESS;
}

template <class T>
void WriteImage(T image, std::string filename)
{

}

The problem here seems to be re-using the template parameter as the parameter for another template for some reason?

I don't understood the problem. An example, perhaps?

#include <itkImage.h>
#include <itkImageFileWriter.h>
#include <itkRescaleIntensityImageFilter.h>

template <class T>
void WriteImage(T image, std::string filename);

int main(int, char *[])
{
  itk::Image<unsigned char, 2>::Pointer image = itk::Image<unsigned char, 2>::New();
  WriteImage<itk::Image<unsigned char, 2> >(*(image), "test.jpg");

  return EXIT_SUCCESS;
}

template <class T>
void WriteImage(T image, std::string filename)
{

}

That's not what I suggested. That's a pass by value that uses the copy constructor. It's clear that the designer(s) of the library don't want you to do that, which really doesn't surprise me. I suggested a pass by reference, which shouldn't call any constructors:

template <class T>
void WriteImage(typename T [B]&[/B]image, std::string filename);

/* ... */

template <class T>
void WriteImage(typename T [B]&[/B]image, std::string filename)
{

  /* ... */

}

Fbody,

Ah, yes, it worked when I passed by reference, thanks.

Another alternative I found:

#include <itkImage.h>
#include <itkImageFileWriter.h>
#include <itkRescaleIntensityImageFilter.h>

template <class T>
void WriteImage(typename T::Pointer image, std::string filename);

int main(int, char *[])
{
  itk::Image<unsigned char, 2>::Pointer image = itk::Image<unsigned char, 2>::New();
  WriteImage<itk::Image<unsigned char, 2> >(image, "test.jpg");

  return EXIT_SUCCESS;
}

template <class T>
void WriteImage(typename T::Pointer image, std::string filename)
{
  typedef itk::RescaleIntensityImageFilter<T, T> RescaleFilterType;
  typename RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); //note the use of typename here
}

itk::RescaleIntensityImageFilter<T,T>::Pointer is a "dependent name" -- i.e. it depends on the template parameter T, so you have to use typename for the filter as well.

Thanks for all of the discussion/help!

David

Wait a minute,

if i understand properly, do you really want to do this:

itk::RescaleIntensityImageFilter<itk::Image<unsigned char, 2>::Pointer , 
  itk::Image<unsigned char, 2>::Pointer >::Pointer RescaleFilterType =
  itk::RescaleIntensityImageFilter<itk::Image<unsigned char, 2>::Pointer , 
  itk::Image<unsigned char, 2>::Pointer >::New();

Because so far i understood, you are creating pointer to pointer type class and most probably that RescaleIntensityImageFilter class wont be able to Pointer to Pointer.

EDIT: OK so it is already solved!! great.

So you following code works, which is understandble because you are creating a RescaleIntensityImageFilter class of itk::Image<unsigned char, 2> type and its not POINTER.

itk::RescaleIntensityImageFilter<itk::Image<unsigned char, 2> ,   
    itk::Image<unsigned char, 2> >::Pointer RescaleFilterType =
    itk::RescaleIntensityImageFilter<itk::Image

So, you have to use it this way to generate class and create the object, but after creating the object you need to set those two parameter:

your class has following memeber method:

virtual void 	SetInput (const InputImageType *image)

so, all i want to say, you most probably wont be able to initialize this RescaleIntensityImageFilter as a POINTER Type.

Great! Glad you figured it out.

itk::RescaleIntensityImageFilter<T,T>::Pointer is a "dependent name" -- i.e. it depends on the template parameter T, so you have to use typename for the filter as well

I'll have to file that one away, thanks for the tip.

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.