I'm pretty sure the answer is "you can't use templates, you have to use virtual functions (dynamic polymorphism)", but it seems like I'd have to duplicate a lot of code if I went that route. Here is the setup:
I currently have two classes, ColorImageSegmentation and GrayscaleImageSegmentation. They do essentially the same thing, but there are three differences
- they operate on different types (ColorImage and GrayscaleImage)
- a parameter, the dimensionality of the histogram (3 vs 1) is different
- The PixelDifference function is different based on the image type
If I create a class
template <TImageType>
class ImageSegmentation
{
};
I would be in good shape. However, I want to have this object as a member of another class:
class MyMainClass
{
ImageSegmentation MyImageSegmentation;
};
But the user needs to determine the type of MyImageSegmentation (if the user opens a grayscale image, I want to instantiate MyImageSegmentation<GrayScaleType>. Likewise for a color image, MyImageSegmentation<ColorType>.)
With derived classes, I could store a pointer and then do:
class MyMainClass
{
ImageSegmentation* MyImageSegmentation;
};
... user does something...
MyImageSegmentation = new ColorImageSegmentation;
but how would I do something like this with templates? The problem is I have a lot of:
typedef TImageType::HistogramType HistogramType;
typedef TImageType::PixelType PixelType;
sort of things going on, so I don't know how I would convert them to the dynamic polymorphic model without duplicating a whole bunch of code.
Sorry for the rambling... does anyone have any suggestions for me?
Thanks,
David
Maybe there are additional requirements you haven't told us about, but from what you have so far, you can pass the type down through the containing class:
template<typename TImage>
class MyMainClass
{
ImageSegmentation<TImage> MyImageSegmentation;
};
Most likely you'll need some layer of dynamic dispatch, but only at the highest level of abstraction:
struct IMainClass
{
virtual bool SaveToFile(std::string filename) = 0;
virtual bool ApplySharpenFilter(int level) = 0;
...
};
template<typename TImage>
class MyMainClass : public IMainClass
{
ImageSegmentation<TImage> MyImageSegmentation;
public:
virtual bool SaveToFile(std::string filename);
virtual bool ApplySharpenFilter(int level);
};
IMainClass* pMain = new MyMainClass<GrayscaleImage>();
You want to create a templated version of your objects but have those objects take different parameter types based on the templated parameter? That's not a very easy thing to integrate into a library but there are a few ways of going about it.
Take a look at unary_function for inspiration. There they are using templated traits to carry around the type parameters without having to work any sort of magic:
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
};
'unary_function' does not contain any functionality other than declaring typedefs. These typedefs, however, allow you to express in code and at compile time named equivalents between code segments. They leverage the way template parameters are checked.
What this means is that you can have objects that work on this:
template<typename T>
struct Foo{
typedef typename T::argument_type argument_type;
Foo(T _myFunc) : m_Func(_myFunc)
void myWrappedFunction(argument_type _argument){ m_Func( _argument ); }
};
which contains within it the value type of the arguments without having to specify them in advance. So if you have pixel_type or something similar for each of your image objects then simply stating typename T::pixel_type will call forward the type parameter you need.
Related
I have written two different container classes, which have the same interface but use different member data and algorithms to operate on their members. I also have a template function that takes a container and does some useful calculation:
class Container1
{
// implementation here
};
class Container2
{
// implementation here
};
template<typename ContainerType>
void my_function(ContainerType const& container, /* other parameters */)
{
// ...
}
What bothers me is the fact that 'my_function' should only accept Container1 or Container2, but this is not expressed by the code, since ContainerType can be any type. The function is templated by container type since it does the same thing no matter what is the internal implemetation of container.
I am considering a variant where Container1 and Container2 would be full specializations of a template class. Then I could be more specific about the argument of my_function:
template<typename T>
class Container;
// Tags to mark different container types
struct ContainerType1 { };
struct ContainerType2 { };
template<>
class Container<ContainerType1>
{
// implementation
};
template<>
class Container<ContainerType2>
{
// implementation
};
template<typename T>
void my_function(Container<T> const& container, /* other parameters */)
{
}
In the first case, the compilation with a wrong template parameter will fail if 'ContainerType' does not have the interface required by my_function, which is not very informative. In the second case, I would also get a compiler error (failed template parameter deduction) if I supply anything else than Container<ContainerType1> or Container<ContainerType2>, but I like it better since it provides a hint about what kind of template parameter is expected.
What are you thoughts about this? Is it a good design idea or not? Do you think it is worth the change in the code? There are many other functions like my_function in the code and sometimes it is not obvious what kind of template parameters they expect. What are my other options to make my_function more specific? I am aware the existence of Boost Concept Check Library.
For the sake of argument, let's suppose that I don't want to solve the problem by using inheritance and virtual functions.
In case it is relevant to the discussion, the common interface of Container1 and Container2 is imposed by using CRTP. There might be more container classes in the future.
There are a few solutions to this kind of problem.
Your solution (implementing your types as a template specialization) is one, but one I don't particularly like.
Another is the CRTP:
template<typename T>
struct Container {
// optional, but I find it helpeful
T* self() { return static_cast<T*>(this); }
T const* self() const { return static_cast<T const*>(this); }
// common code between every implementation goes here. It accesses itself through self(), never this
};
class ContainerType1: public Container<ContainerType1> {
// more details
};
class ContainerType2: public Container<ContainerType2> {
// more details
};
that is the core of the CRTP.
Then:
template<typename T>
void my_function(Container<T> const& container_, /* other parameters */)
{
T const& container = *(container.self());
}
and bob is your uncle. As a bonus, this provides a place to put common code.
Another option is a tag traits class that marks the types you want to support, like iterator_traits.
template<typename T>
struct is_container : std::false_type {};
template<>
struct is_container<ContainerType1> : std::true_type {};
template<>
struct is_container<ContainerType2> : std::true_type {};
you can even do SFINAE style pattern matching to detect a base type (like how iterators work).
Now your method can test on is_container<T>::value, or do tag dispatching on is_container<T>{}.
I think your first version is do-able.
At the end of the day, you always have to choose the optimum approach. Second one may look like an overkill although it gets the point across.
If you Container classes will both have a common function (let's say Container1::hasPackage() or Container2::hasPackage() and you choose to call it within my_function then it straight away puts your point across that the eligibility to call it is that function itself. After going through many such projects you will start reading the templates in a reverse manner - starting from the template definition - to see what least properties are needed qualify a particular class.
Having said all this, perhaps your question was more suited for Code Review
One example I created on ideone was using your classes but adding a member variable name to them both which is expected by my_function. Of course there may be classes that will support name but the developer may also burn his fingers a few times to realize the idea behind the function.
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.
I'm trying to a design for a system where the user can define their own class as an aggregate of a number of predefined components, and then have this class work with algorithms which I provide. I am trying to do this with compile time and/or template based approaches rather than run time polymorphism or virtual functions as performance is important in this case.
For example, consider that I have a number of components which can be used to build a 3D vertex. I will define these components as Position, Normal, Color, etc, and then the user will be able (via multiple inheritance, composition, or what?) to define a vertex such as PositionAndColorVertex which has only position and color but no normal . Now, I provide a function which does some processing on a vector of one million these vertices:
template<typename UsersVertexType>
void myProvidedAlgorithm(std::vector<UsersVertexType> input)
{
if(vertex has a position)
//do stuff with position
if(vertex has a normal)
//do stuff with normal
if(vertex has a color)
//do stuff with color
}
Now, I don't know what UsersVertexType will look like but it will be built from my components. My functions needs to do something with each of the components but only if they exist. What is an elegant and fast (compile time) way of expressing this?
Of course, I could define a base class for each type, make the user inherit from the desired base classes, and then use dynamic_cast to check which components are implemented, but this is exactly the sort of runtime approach I would like to avoid. Perhaps I can check this inheritance relationship at compile time (the compiler should know what UsersVertexType actually is, right?).
Perhaps my components should be expressed using C++ concepts or policies? I've also seen talk of mixins but not sure these are useful. Should the users class use multiple inheritance or composition? Maybe I should somehow get a set of flags into the users class, indicating what it contains? How would you design this system?
Thanks for any insight!
Note: There are similarities to my previous question, but here I am taking a step back and looking for higher level design options/alternatives.
The usual pattern is using type_traits, and/or the use freestanding function templates that can be specialized for the UserVertexType.
Add a bit of SFINAE overload selection magic and voila: you have invented template meta-programming and Boost Graph Library.
Small idea sample:
template <typename VertexType>
struct vertex_traits // default vertex_traits:
{
typename unused_tag position_type;
enum {
hasNormal = 0 // treat as 'boolean'
hasColor = 0
};
};
template <typename V> vertex_traits<V>::position_type& position(V&);
The idea is, that by making the generic stuff be defined outside the class you don't impose any unnecessary restrictions on the user's choice of vertex type (they could just use std::pair, they might just pass a third party type and decorate it for use with your graph library etc.)
Google: "How Non-Member Functions Improve Encapsulation" (by Scott Meyer)
Traits and template specializations.
#include <iostream>
template <typename V> struct traits; // Primary template.
Then define a version for your vertices with positional component, and one for vertices without:
template <typename Vertex, bool has_position=traits<Vertex>::has_position>
struct some_position_op;
template <typename Vertex> struct some_position_op<Vertex,false> {
void operator() () { std::cout << "has no position.\n"; }
};
template <typename Vertex> struct some_position_op<Vertex,true> {
void operator() () { std::cout << "has position.\n"; }
};
Finally, for each vertex-type you define, implement a traits class:
struct MyVertexWithPosition {};
template <>
struct traits<MyVertexWithPosition> {
static constexpr bool has_position = true;
};
struct MyVertexWithoutPosition {};
template <>
struct traits<MyVertexWithoutPosition> {
static constexpr bool has_position = false;
};
... and have fun:
template <typename Vertex>
void shade (Vertex const &vtx) {
some_position_op<Vertex>() ();
}
int main () {
shade (MyVertexWithPosition());
shade (MyVertexWithoutPosition());
}
You could also specialize function templates, but would have to sacrifice some of the readability of your shade function.
As a kind of factory-method setup I want to register functors which each create objects of a different type, but meet a common interface - i.e all create objects subclassing a core class.
Say I have something like:
template <class T> struct FactoryMethod
{
X* create();
}
I cannot have (IIRC) std::map<std::string,FactoryMethod*> because each FactoryMethod template specialization is a separate type. But I could do:
struct IFactoryMethod
{
virtual X* create()=0;
};
template <class T> struct FactoryMethod : public IFactoryMethod
{
virtual X* create();
};
std::map<std::string,IFactoryMethod*> factories;
Right? I am not aware standard STL has a way to make this neater though I guess boost does - however we don't use boost right now and I am interested anyway.
The idea is then factories can be looked up based on type-name (read from XML for instance) to create the right type.
This is known as type erasure and is a fairly common idiom- although your map could of course be made of ownership-enforcing pointers and you could also use a virtual destructor like most sane people.
I want to implement a Mesh class for a CG project, but have run into some problems.
What I want to do is a Mesh class that hides implementation details (like loading to a specific API: OpenGL, DirectX, CUDA, ...) from the user. Additionally, since the Mesh class will be used in research projects, this Mesh class has to be very flexible.
class Channel {
virtual loadToAPI() = 0;
}
template <class T>
class TypedChannel : public Channel {
std::vector<T> data;
};
template <class T>
class OpenGLChannel : public TypedChannel<T> {
loadToAPI(); // implementation
};
class Mesh {
template<class T>
virtual TypedChannel<T>* createChannel() = 0; // error: no virtual template functions
std::vector<Channel*> channels;
};
class OpenGLMesh {
template<class T>
TypedChannel<T>* createChannel()
{
TypedChannel<T>* newChannel = new OpenGLChannel<T>;
channels.push_back(newChannel);
return newChannel;
};
};
For flexibility, each Mesh is really a collection of channels, like one position channel, a normal channel, etc. that describe some aspects of the mesh. A channel is a wrapper around a std::vector with some added functionality.
To hide implementation details, there is a derived class for each API (OpenGLMesh, DirectXMesh, CUDAMesh, ...) that handles API-specific code. The same goes for the Channels (OpenGLChannel, etc. that handle loading of the Channel data to the API). The Mesh acts as a factory for the Channel objects.
But here is the problem: Since the Channels are template classes, createChannel must be a template method, and template methods cannot be virtual. What I would need is something like a Factory Pattern for creating templated objects. Does anyone have advice on how something similar could be accomplished?
Thanks
It's an interesting problem, but let's discuss the compiler error first.
As the compiler said, a function cannot be both virtual and template. To understand why, just think about the implementation: most of the times, objects with virtual functions have a virtual table, which stores a pointer to each function.
For templates however, there are as many functions as combinations of type: so what should be the virtual table like ? It's impossible to tell at compilation time, and the memory layout of your class includes the virtual table and has to be decided at compilation time.
Now on to your problem.
The simplest solution would be to just write one virtual method per type, of course it can soon become tedious, so let's pretend you haven't heard that.
If Mesh is not supposed to know about the various types, then surely you don't need the function to be virtual, because who would know, given an instance of Mesh, with which type invoking the function ?
Mesh* mesh = ...;
mesh.createChannel<int>(); // has it been defined for that `Mesh` ??
On the other hand, I will suppose that OpenGLMesh does know exactly which kind of TypedChannel it will need. If so, we could use a very simple trick.
struct ChannelFactory
{
virtual ~ChannelFactory() {}
virtual Channel* createChannel() = 0;
};
template <class T>
struct TypedChannelFactory: ChannelFactory
{
};
And then:
class Mesh
{
public:
template <class T>
Channel* addChannel()
{
factories_type::const_iterator it = mFactories.find(typeid(T).name());
assert(it != mFactories.end() && "Ooops!!!" && typeid(T).name());
Channel* channel = it->second->createChannel();
mChannels.push_back(channel);
return channel;
} // addChannel
protected:
template <class T>
void registerChannelFactory(TypedChannelFactory<T>* factory)
{
mFactories.insert(std::make_pair(typeid(T).name(), factory));
} // registerChannelFactory
private:
typedef std::map < const char*, ChannelFactory* const > factories_type;
factories_type mFactories;
std::vector<Channel*> mChannels;
}; // class Mesh
It demonstrates a quite powerful idiom known as type erasure. You probably used it even before you knew the name :)
Now, you can define OpenGLMesh as:
template <class T>
struct OpenGLChannelFactory: TypedChannelFactory<T>
{
virtual Channel* createChannel() { return new OpenGLChannel<T>(); }
};
OpenGLMesh::OpenGLMesh()
{
this->registerChannelFactory(new OpenGLChannelFactory<int>());
this->registerChannelFactory(new OpenGLChannelFactory<float>());
}
And you'll use it like:
OpenGLMesh openGLMesh;
Mesh& mesh = openGLMesh;
mesh.addChannel<int>(); // fine
mesh.addChannel<float>(); // fine
mesh.addChannel<char>(); // ERROR: fire the assert... (or throw, or do nothing...)
Hope I understood what you needed :p
If you could extract factory from Mesh (introducing some ChannelFactory), then you can use templatized factory:
template <class T>
class ChannelFactory
{
public:
virtual TypedChannel<T>* createChannel() = 0;
};
Than you could derive your OpenGLMesh from ChannelFactory, , , whatever.
The only limitation of this approach is that you should know beforehand which template parameters you want use in OpenGLMesh.
Otherwise you could be interested how Boost.Any works (boost::any holds values of arbitrary type).
I'd say your whole design is broken.
virtual TypedChannel<T>* createChannel() = 0; // error: no virtual template functions
std::vector<Channel*> channels;
These two lines just don't make any sense together. Don't try to fix compiler error, think over your concepts.
To start, what exactly is your reasoning for making CreateChannel a virtual member?
To put it another way, C++ is a language known for allowing all kinds of tangled unintelligible designs. And you managed to design something that even C++ thinks is too twisted.
By channel do you mean 'spacial index'?
If you want to hide implementation details, why do you have them right in your mesh?
You want the mesh to be the same basic format, maybe templating on float, double or morton numbers in different cases. It's not the mesh that should change, just the way it gets loaded.