Important: This question is getting quite long, if this is the first time you're reading this I suggest you start near the bottom as the solution is there in a round about way, but the code is a bit smelly.
After reading a tutorial on templates, I was able to change my existing class to support generic types. However, many objects are already dependent on this, so I'm looking for a way of making a method generic rather than the entire class.
I've tried the following, but it looks like this behavior isn't supported.
// foobar1.h
// Don't want the entire class to be generic.
//template<class T>
class FooBar1
{
public:
template<class T> T Foo();
}
// foobar2.h
class FooBar2 : public FooBar1
{
}
// foobar1.cpp
template<class T>
T FooBar1::Foo()
{
return something;
}
// test.cpp
FooBar1 fb1;
FooBar2 fb2 = fb1.Foo<FooBar2>();
Is this supposed to not work, or is it a bug elsewhere that I'm getting confused with?
undefined reference to
FooBar2 Foo<FooBar2>()
To put this in to some sort of perspective as to what I want to achieve, here's how I'd do it in C#...
pubic class FooBar1
{
public T Foo<T>()
where T : FooBar1
{
return something;
}
}
public class FooBar2 : FooBar1 { }
FooBar1 fb1 = new FooBar1();
FooBar2 fb2 = fb1.Foo<FooBar2>();
Is there any way I can do something similar to that in C++?
Update 1:
Just corrected some minor syntax details (I meant to make Foo public, and return T, not FooBar2). Still getting compiler error... When I remove the template behavior the error goes away, the answer so far say what I'm doing is valid... but if it is then why am I getting the error still? Thanks for your answers!
Update 2:
Josh, here's the actual source code (well, what I think is relevant, anwyay - let me know if you think I've skipped an important bit).
// ImageMatrix.h
class ImageMatrix : public VImage
{
public:
// ... various functions ...
template<class T> T GetRotatedCopy(VDouble angle);
}
// ImageFilter.h
class ImageFilter : public ImageMatrix
{
// ... various functions ...
}
// ImageMatrix.cpp
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
// ... create a new instance of ImageMatrix and return it.
}
// ImageProcessor.cpp
ImageFilter filter2 = filterPrototype.GetRotatedCopy<ImageFilter>(90);
And here's the actual compiler error:
/home/nick/Projects/ViMRID/vimrid/Debug/libvimrid.so: undefined reference to `vimrid::imaging::processing::ImageFilter vimrid::imaging::ImageMatrix::GetRotatedCopy(double)'
Update 3:
By the way, everything but the implementation line is located in a library; so it's being called from a separate binary... Does this matter? Correction; its all in the same library. All blocks are different files though.
Update 4:
When I comment out the implementation line (ImageFilter filter2 = filterPrototype...) it builds fine, so it seems to be this line thats causing it...
Update 5 (Solved?):
Still having problems... Could this be a problem with the namespaces? Scratch that, OK, I've grasped the concept of templates now! :) The template definition must be in the header along with the declaration (right?) - so now that I've moved the declaration in to ImageMatrix.h
, everything compiles. However, I've had to use dynamic_cast
to get it working; is this right? If I'm way off please correct me!
// This is in the header file!
// Help!!! This looks really really smelly...
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
ImageMatrix image = _getRotatedCopy(angle);
ImageMatrix *imagePtr = ℑ
return *dynamic_cast<T*>(imagePtr);
}
Update 6:
Refering to update 5, when I don't use dynamic_cast...
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
ImageMatrix image = _getRotatedCopy(angle);
ImageMatrix *imagePtr = ℑ
//return *dynamic_cast<T*>(imagePtr);
return *imagePtr;
}
... I get this error ...
../src/imaging/processing/../ImageMatrix.h: In member function ‘T vimrid::imaging::ImageMatrix::GetRotatedCopy(vimrid::VDouble) [with T = vimrid::imaging::processing::ImageFilter]’:
../src/imaging/processing/ImageProcessor.cpp:32: instantiated from here
../src/imaging/processing/../ImageMatrix.h:45: error: conversion from ‘vimrid::imaging::ImageMatrix’ to non-scalar type ‘vimrid::imaging::processing::ImageFilter’ requested
make: *** [src/imaging/processing/ImageProcessor.o] Error 1
Update 7:
Also, if I don't use all of that smelly code in update 6...
class ImageMatrix : public VImage
{
public:
template<class T> T GetRotatedCopy(VDouble angle);
private:
ImageMatrix _getRotatedCopy(VDouble angle);
};
template<class T>
T ImageMatrix::GetRotatedCopy(VDouble angle)
{
return _getRotatedCopy(angle);
}
... I get the same error as in update 6.