A collection of template objects with different template parameters - c++

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.

Related

Storing templated objects in a vector (Storing Class<int>, Class<double> in a single vector)

There is a templated class, let it be
template<typename T> class A { std::vector<T> data; };
The problem I am facing here is, users can create several types of this class, but I need to track them, best case is I have a reference of these objects in another vector, but that would not work since all types are different.
Can you recommend a good design pattern which can encapsulate this.
I can store pointers and then typecast it, but its not elegant.
I can change the architecture as well, if the solution provided is good enough.
The basic question I am trying to solve is, I have a class of vector of custom types, how do I store them.
As previous comments stated - you first need to make sure this is what you need.
With that been said, I had a similar requirement in a project of mine, which I eventually solved with inheritance and PIMPL, as follows:
class A{
private:
struct Abstract {
virtual void f() = 0;
};
template <typename T>
struct Implementation : public Abstract {
std::vector<T> data;
virtual void f() {...}
};
std::unique_ptr<Abstract> impl;
public:
template <typename T>
A(): impl(std::make_unique<Implementation<T> >()){}
void f() {impl->f();}
};
This allows you to create a container of objects of type A, and access them via the public interface defined therein (the method f). The underlying type T of each A object is specified on construction. All other implementation details specific to the type T are hidden.
The solution suffers the inherent overhead of virtual functions. I'm not sure how it compares to the std::any approach performance-wise.
std::any is the modern c++17 solution. Specifically, you should use
A<int> a;
a.data.push_back(0);
// fill refernces...
std::vector<std::any> refernces;
refernces.push_back(&a.data[0]);
// check which type is active.
if(int** iPtr = std::any_cast<int*>(&references[0]); iPtr != nullptr)
{
// its an int*
int& i = **iPtr;
// do something with i.
}
These pointers can point into the A<int>::data and A<double>::data vectors.
For a complete reference, see here https://en.cppreference.com/w/cpp/utility/any.

Is the only way to "polymorphically" declare a member of a non-specialized template type, by defining a base class?

Suppose we have a templated class,
template<typename Type>
class Container {};
Of course, we can't do this:
struct Foo
{
Container _container;
}
But what if we wanted to do something like it? Is the only way to do this, to define a base class,
class ContainerBase {};
template<typename Type>
class Container : public ContainerBase {};
and store a pointer, like below?
struct Foo
{
ContainerBase* _container;
}
It's simple enough, but it feels weird to have to add a base class solely for that reason, when it seems the compiler should have enough information to imply a set of related specializations. Of course, regardless _container needs to be a pointer, else Foo couldn't resolve to a static size, but
struct Foo
{
Container* _container;
}
doesn't work either.
it seems the compiler should have enough information to imply a set of related specializations.
Nope. Template specializations are totally unrelated except in name, and the name of a type has essentially no bearing on runtime operation. Specializations of a given template usually share a (mostly) common interface, but they could just as well be completely different.
Adding a base class is essential if you want to relate between the specializations. And if they share so much in common, factoring that functionality into the base is a pretty great idea.

Fully specialized class as template function parameter

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.

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.

Forcing class inheritance in c++11 for wrapped classes -- is it a bad thing?

I've been working on a wrapping library for scripted languages (partially to learn c++11 features, and partially for a specific need). One issue that has come up is that of exporting inherited objects to the scripted language.
The problem involves using proxy objects of wrapped classes for the invocation of functions. Specifically, if a function takes a Foo *, then the object proxy from whatever scripted language is being used must be cast appropriately.
There are two ways (that I can think of) to model the object proxy appropriately:
template <class T>
struct ObjectProxy {
T *ptr;
};
or:
struct WrappedClass {
virtual ~WrappedClass() {}
};
struct ObjectProxy {
WrappedClass *ptr;
template <typename T>
boost::shared_ptr<T> castAs() {
return boost::dynamic_pointer_cast<T>(instance);
}
};
The problem with the first version is that you need to know ahead of time what type ObjectProxy is pointing to. Unfortunately, there is no easy solutions to this (see many of my previous questions). After some investigation, it looks like most of the popular libraries that do this (e.g. boost::python, LuaBind, etc.) keep a graph of all the class relationships in order to allow for the proper casting.
The second method avoid having to do all that, but does add the constraint that every class you wrap must inherit from WrappedClass.
Here's my question: can anyone think of any major problems, besides being slightly annoying to the user, with the second approach? Even if you didn't make a specific class, you should always be able to subclass it. For example, if you had some library the provide class Foo, then you could do:
class FooWrapped: public Foo, public WrappedClass {};
This does make things a little less seamless for the user (though I've been looking into ways of automating this), it does mean you can rely on the built-in dynamic_cast rather than having to write your own variant.
edit
Added castAs() to make use-case clearer
Your problem sounds like what boost::any was designed to solve. The solution basically combines your two ideas: (code untested)
struct ObjectProxyBase {
virtual ~ObjectProxyBase() {}
};
template <class T>
struct ObjectProxy : public ObjectProxyBase {
T *ptr;
};
template <class T>
T *proxy_cast(ObjectProxyBase *obj) {
auto ptr = dynamic_cast<ObjectProxy<T> *>(obj);
if (!ptr)
return nullptr;
return ptr->ptr;
}