C++ Calling function that has template which has inheritance - c++

So I have a class that defines a TileGrid:
template<typename T>
class TileGrid { ... };
I fill in the template with a class called ImageTile
class ImageTile { ... };
I have a child class of ImageTile that I have defined that looks like this:
class FFTWImageTile : public ImageTile { ... };
In a separate file I define the following function:
void writeDataToFile(TileGrid<ImageStitching::ImageTile> * grid, std::string fileName);
(note: both ImageTile and FFTWImageTile are in the ImageStitching namespace)
Now all of the above compiles just fine, but when I try to use it I get an error.
Here is an example test case that is using it:
namespace is = ImageStitching;
TileGrid<is::FFTWImageTile> * grid = new TileGrid<is::FFTWImageTile> ( ... );
writeTranslationsToFile(grid, "output.txt");
When compiling the test case I get the following error:
error: cannot convert ‘TileGrid<ImageStitching::FFTWImageTile>*’ to ‘TileGrid<ImageStitching::ImageTile>*’ for argument ‘1’ to ‘void writeTranslationsToFile(TileGrid<ImageStitching::ImageTile>*, std::string)’
Anyway I can make this happen in C++?? I've looked all over and cant seem to find some help with making a function that has a parameter featuring a template that has child/parent relationships.
Edit:
Everyone's answers have been exceptional and each solve the issue presented. I think decided to move to C++11 and use an assert for this particular case. In the future I think I will add a template to the function and ensure to get the data that way. Thank you all for the help! I have marked what I think is the best answer although each have been acceptable.

You are getting the error because despite that FFTWImageTile is derived from ImageTile, TileGrid<FFTWImageTile> and TileGrid<ImageTile> are absolutely unrelated classes.
How to fix this depends on the implementation of the classes which you haven't shown. Perhaps you can make writeDataToFile() templated:
template<typename T>
void writeDataToFile(TileGrid<T> * grid, std::string fileName);

Options that might work for you.
Make writeDataToFile a function template.
template <typename T>
void writeDataToFile(TileGrid<T> * grid, std::string fileName);
In the implementation of this function, use another function template to write individual elements of the tile.
template <typename T>
void writeTileElement(T const& tileElement, std::ostream& out);
You can create overloaded versions of writeTileElement to take care of special handling of different types of objects.
Use a TileGrid of ImageTile* instead of ImageFile.
void writeDataToFile(TileGrid<ImageStitching::ImageTile*> * grid, std::string fileName);

You generate two different classes with
TileGrid<ImageStitching::ImageTile>
and
TileGrid<is::FFTWImageTile>
They have no relation other than being generated from the same template. You would want to derive from the class TileGrid<ImageStitching::ImageTile> to have an actual subclass for type purposes.
You could templatize the function writeDataToFile, but to enforce type restrictions on template arguments, you should use something like...
static_assert(is_base_of<T, ImageStitching::ImageTile>>(), "T is not a base of ImageTile");
static_assert
is_base_of

Related

Using Concepts to create static polymorphic interface

Hello Stackoverflow community,
I've been really confused on the concepts syntax and am having a hard time getting started.
I would like to create a polymorphic interface for two types of operator types: unary and binary and opted to try out the concept feature in c++20.
Not sure if it matters, but I used a CRTP create my unary functor compatible with binary functors, however I would like to get rid of that. Here's what I have so far:
template <typename T>
concept UnaryMatrixOperatable = requires(T _op) {
_op.template operate(std::unique_ptr<Matrix::Representation>{});
{_op.template operate() } -> same_as<std::unique_ptr<Matrix::Representation>>;
};
class ReLU : public UnaryAdapter<ReLU> {
public:
std::unique_ptr<Matrix::Representation> operate(
const std::unique_ptr<Matrix::Representation>& m);
};
static_assert(UnaryMatrixOperatable<ReLU>);
However, I am getting a compilation error, presumably because I am not doing some sort of template specialization for a const matrix & type?
include/m_algorithms.h:122:13: error: static_assert failed
static_assert(UnaryMatrixOperatable<ReLU>);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/m_algorithms.h:122:27: note: because 'Matrix::Operations::Unary::ReLU' does not satisfy 'UnaryMatrixOperatable'
static_assert(UnaryMatrixOperatable<ReLU>);
^
include/m_algorithms.h:53:26: note: because '_op.template operate(std::unique_ptr<Matrix::Representation>{})' would be invalid: 'operate' following the 'template' keyword does not refer to a template
_op.template operate(std::unique_ptr<Matrix::Representation>{});
^
Thanks for all the help in advance, this design in my code has been problematic for over a week so I'm determined to find a clean way to fix it! Thanks.
Concepts are not base classes, and you should not treat concept requirements like base class interfaces. Base classes specify exact function signatures that derived classes must implement.
Concepts specify behavior that must be provided. So you explain what that behavior is.
The behavior you seem to want is that you can pass an rvalue of a unique pointer to an operate member function. So... say that.
template <typename T>
concept UnaryMatrixOperatable = requires(T _op, std::unique_ptr<Matrix::Representation> mtx)
{
_op.operate(std::move(mtx));
};
There's no need for template here because you do not care if operate is a template function. It's not important in the slightest to your code if any particular T happens to implement operate as a template function or not. You're going to call it this way, so the user must specify some function interface that can be called a such.
The same goes for the zero-argument version. Though your interface should probably make it much more clear that you're moving from the unique pointer in question:
template <typename T>
concept UnaryMatrixOperatable = requires(T _op, std::unique_ptr<Matrix::Representation> mtx)
{
_op.operate(std::move(mtx));
{ std::move(_op).operate() } -> std::same_as<decltype(mtx)>;
};
In any case, the other reason you'll get a compile error is that your interface requires two functions: one that gets called with an object and one that does not. Your ReLu class only provides one function that pretends to do both.

Call function of template class created at runtime

I have a tricky question about C++(11) template classes and their instantiation with types determined at runtime:
Following scenario:
The user defines the type of a template class using a config file (ROS parameters). This determines only the type of the template class, not the further logic:
Class definition:
template<typename T>
class MyClass {
//[...]
}
Exemplary code:
/* [Read parameter and write result to bool use_int] */
std::unique_ptr<MyClass> myclassptr {nullptr};
if(use_int) {
myclassptr.reset(MyClass<int>);
} else {
myclassptr.reset(MyClass<double>);
}
myclassptr->foobar();
/* [more code making use of myclassptr] */
So this code is (of course) not compiling, because the unique_ptr template must be specified also with the template type. However, then the problem arises that the template type must be the same for all objects assigned using reset.
One ugly solution would be to copy the code myclassptr->foobar(); and the following into each branch of if/else, which I really don't like.
I would like to see a solution similar to this:
/* [Read parameter and write result to bool use_int] */
MyClass<use_int ? int : double> myclass;
myclass.foobar();
What I have read so far is that something like this is also not possible.
Does anybody have a nice solution for this?
The simplest way to do this is:
class IClass{
virtual ~IClass {}
virtual void foobar()=0;
};
template<typename T>
class MyClass:public IClass {
public:
void foobar() override {
// code here
}
};
std::unique_ptr<IClass> myclassptr {};
if(use_int) {
myclassptr.reset(new MyClass<int>());
} else {
myclassptr.reset(new MyClass<double>());
}
myclassptr->foobar();
boost::variant would be another solution, but is usually used for unrelated types. Type erasure could be done, but again that is usually done when you have unrelated types you want to impose a uniform interface on.
In other languages generics look sort of like templates, but are actually an abstract interface with auto-generated typecasting and some typechecking added. C++ templates are function or class compile time factories. Two outputs of such factories are unrelated at runtime by default, and you can add such relations if you want.
Depending on what you want, you can make MyClass a variant type that holds either an int or a double, or you could use type erasure to hide the implementation behind an interface. The Boost.Variant library can help to implement the former.

Template class specialization to handle its own type

I've been playing around with templates to get a feel for them and i wanted to do a class specialization on its own type. I searched the internet for a while but i found no mention of this.
For example if i have a class Array:
template<class T>
class Array{
...
void print();
}
Is it possible to specialize method print() when T=Array<unspecified type>?
template<class T>
void Array<Array<T>>::print(){
//do something diffrent for array of array
//this code wont work
}
I managed to do this
template<>
void Array<Array<int>>::print(){
//print in matrix format
//this code works
}
I don't see this feature being extremely useful, but i was nonetheless curious
AFAIK you can perform a specialization only for the whole class. Once I needed something like that (actually, I just needed two typedefs to be different), so I created an auxiliary class which contained only the members that had to be specialized, and made the principal class inherit from it.
There is a feature called partial specialization where you could apply something like this. However, I don't believe that you can partially specialize member functions without partially specializing the whole class.

Template specialization priorities when using pointers or references

I have a Serializer class like this:
class Serializer
{
public:
// Func 1 (default)
template <class T>
void Serialize(T* pValue)
{
SerializeInternal(reinterpret_cast<char*>(pValue), sizeof(*pValue));
}
// Func 2 (specialization)
template <>
void Serialize<Serializable>(Serializable* pSerializable)
{
pSerializable->Serialize(*this);
}
protected:
// Implemented by input and output serializers
virtual void SerializeInternal(char* pData, size_t size) = 0;
};
Now my problem is when I have classes that inherit the Serializable interface they will always be handled by Func 1, even though I want them to be handled by Func 2 (pointers or references doesn't matter they both behave equally). It seems like C++ doesn't recognize that the Serializable interface is inherited unless you clearly specify that:
SerializableClass sc; // Inherits Serializable
InputSerializer s; // Inherits Serializer
s.Serialize(&sc); // Func 1 is called >:(
s.Serialize<Serializable>(&sc); // Func 2 is called
Now as soon as I forget to add <Serializable> somewhere the program of course bugs out, which is pretty annoying.
Is there any way around this?
It seems like C++ doesn't recognize that the Serializable interface is inherited unless you clearly specify that
This is true. If you have some class
class SerializableClass : public Serializable
only SerializableClass, not Serializable, is considered when deducing the T parameter.
If what you need is create two functions, one taking any pointer, the other taking a pointer to anything derived from Serializable, you can create two overloads and use SFINAE to select the narrower one when possible.
template <class T>
typename boost::enable_if_c<!boost::is_base_of<Serializable, T>::value, void>::type foo(T*) { ... }
template <class T>
typename boost::enable_if<boost::is_base_of<Serializable, T>, void>::type foo(T*) { ... }
If you don't want to use boost, you can implement required functionality akin to this.
Use an overload instead of a template specialization!
I found a link explaining how boost::is_base_of works: How does `is_base_of` work?
Apparently they use some pretty fancy template-fu magic to get it to work. I can "easily" write a similar function myself.
When you're not clever enough to solve it yourself, look at the pros ;)

Any way to determine if class implements operator()

I'm trying to find is there's a way to check if a class is a functional because i want to write a template which uses it?
Is there an easy way to do this? Or do I just wrap things in a try/catch? Or perhaps the compiler won't even let me do it?
If you have a function template written like:
template <typename T>
void f(T x)
{
x();
}
you will be unable to instantiate it with any type that is not callable as a function taking no arguments (e.g., a class type that overloads operator() taking no arguments is callable as a function that takes no arguments). You would get a compilation error if you tried to do so.
This is the simplest way to require the type with which a template is instantiated to have certain properties: just rely on the type having those properties when you write the template, and if the type doesn't have one of the required properties, it will be impossible to instantiate the template with that type.
There are quite a few ways a parameter type can be applicable to the call syntax
Type is a pointer or reference to a function type, or
Type is a class-type which has a conversion function to one of the types in 1., or has an applicable operator().
The current C++ cannot check for 2., so you are left without checking, like the other answers explain.
This would fall under doing it and getting a compiling error. When the code is compiled the template function or template classes are are expanded for the types used as if there were duplicate copies of that template code, one for each type.
So you can basically do whatever and as long as all the types used for your templates support it you have no problem. If they don't support it you have a compiling error and you can't run your code without fixing it.
template <typename T>
void DoIt(T a)
{
a.helloworld();//This will compile fine
return a();//This will cause a compiling error if T is B
}
class A
{
public:
void a.helloworld(){}
void operator()(){}
};
class B
{
public:
void a.helloworld(){}
};
int main(int argc, char**argv)
{
A a;
B b;
DoIt(a);
DoIt(b);//Compiling error
return 0;
}
If you actually need a test to see if type T implements an operator() of some given signature then you could use the same SFINAE trick used to identify the existence of any other class member that is discussed here: C++ "if then else" template substitution