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.
Related
I am a beginner in STL. I'm trying to code a toystl to learn STL. When I code about iterator, I'm puzzled if I should code a simple auto_ptr first and inherint from it.
I wrote a base class called iterator. And now it works like this,
struct iterator{};
template <class T>
struct vector_itorater: public toystl::iterator<toystl::random_access_iterator_tag, T>{};
If i need another base class works like a "auto_ptr"? just like this
// firstly define a sort of auto_ptr as base class
struct auto_ptr{};
// secondly inherint from auto_ptr
template <class T>
struct vector_itorater: public auto_ptr{};
Does this work? Or does STL do it like this?
I think you mixed up runtime polymorphy and compile time polymorphy. When the compiler instantiates a template, it cares about its visible interface of the concrete object. It does not care if this object has a inheritance relationship with other classes, it will pass as long as the concrete object can be used within the concrete context.
template <class C>
void foo(const C& bar)
{
// at the time of writing we don't know anything of C,
// only that it has a callable baz member (either a
// member function or a member with a call operator).
// This works, since the compiler knows the exact type
// during template instantiation, but we don't have to
// care in advance.
bar.baz();
}
struct X
{
void baz() const;
};
void grml()
{
X x;
// The compiler fills in X as the template type
// parameter for us. So the compiler creates a
// void foo<X>(const X&) function for us.
foo(x);
}
In this example when the compiler sees the template, it has no clue how this template will be called later. Only once the template gets instantiated (used), the compiler then will check if the passed type is suitable for this template.
Here it is not needed to have a common base class to derive every possible implementation from. The STL uses templates in order to avoid to use such base classes, since they give you a burden on your design later, and if you have virtual members in the base to override, you can get a serious performance penalty.
Consider this code:
template<typename T, SomeEnum mode> struct TC{
T data;
//...
void doStuff();
};
can "doStuff" have more than one definitions based on the the enum value set for the template?
TC<int, SomeEnum::MODE_1> tc1; tc.doStuff(); //do some stuff
TC<int, SomeEnum::MODE_2> tc2; tc.doStuff(); //do some other stuff
(I don't mean save "mode" and make a branch on it but actually multiple definitions.)
You can do tag dispatch. Just provide an overload for each packaged value of the enum:
template<typename T, SomeEnum mode> struct TC{
T data;
//...
template<SomeEnum v>
using tag_type = std::integral_constant<SomeEnum, v>;
void reallyDoStuff(tag_type<SomeEnum::MODE_1>);
void reallyDoStuff(tag_type<SomeEnum::MODE_2>);
void doStuff() { reallyDoStuff(tag_type<mode>{}); }
};
Because the member functions of a class template won't be instantiated unless used, you'd only instantiate one definition of reallyDoStuff (the proper one) for every instance of TC.
When in doubt, prefer function template overloading to specialization. It's usually the superior alternative.
This is, in general, what template specialization is for. If you don't know what template specializations are, you need to read your C++ book first, before reading the rest of my answer.
The only stumbling block here is that individual class methods cannot be specialized, the entire class must be specialized. But there are common approaches around that, such as the following.
Define your member function as just a function call wrapper to a helper template class, like this:
template<typename T, SomeEnum mode> void TC::doStuff()
{
doStuff_helper<T, mode>::doStuff(*this);
}
That's your actual doStuff(). The actual code goes into the helper class.
Define the helper class template as follows (you will need to properly use forward declarations, and other such miscellanea, of course):
template<typename T, SomeEnum mode> class doStuff_helper {
public:
static void doStuff(TC<T, mode> &me)
{
// ...
}
};
Everything that your original class method did, can now be done here, with some obvious differences. This not the actual method of the original class, any more. So, instead of the original this, you have the me reference here to use. And because this is not the actual class method, there will be the usual issues with accessing private or protected class members. But these are minor details that are easily solved on their own merits. The point is that what you can do now, is specialize the whole thing:
template<typename T> class doStuff_helper<T, MODE_VALUE> {
public:
static void doStuff(TC<T, MODE_VALUE> &me)
{
// ...
}
};
This doStuff() can now be something completely different. This is the general approach for turning class methods specializations, which are not allowed, into ordinary, garden variety, class specialization.
There are further refinements on this general approach that are frequently used. One such refinement would be to have this factored out doStuff() itself be nothing more than a wrapper and a method call to me, with the general and the specialized versions invoking different methods in the original template class.
Once you then work out what happens here, with a piece of paper and a pencil, you will discover that what it ends up doing is turning a single call to the original doStuff() class method into calling two different class methods (which would typically be private), depending on the parameter to the original template class. And those two different class methods would essentially be your two different versions of doStuff() that you wanted to have originally, with only the appropriate method being used depending on the template parameter.
In C# I can define this:
public interface BaseObject
{
int GetValue();
}
public class Test<T> where T : BaseClass
{
T BaseObject;
}
which means I know that I can alwaysa call BaseObject.GetValue() / BaseObject->GetValue(); because I know that the baseobject has this method.
Is there a similiar way to do this in C++? So that I can define an interface that multiple classes can inherit and a class that can take advantage of this.
Templates, which are even more powerful than C# generics (not to say they are necessarily better, just different).
template<class T>
class foo
{
public:
int whatever()
{
return obj.GetValue();
}
private:
T obj;
};
A separate class is created for each template argument you use. If you provide a template type which would result in an error you will know at compile time.
You're asking about C++ concepts, a way to specify requirements for template parameters. They were proposed during the work on C++11, but proved complicated enough that they weren't done in time. But they've just been delayed, not forgotten.
In the meantime, duck typing remains very powerful, and it will catch when you pass a template parameter that doesn't have the required interface. It just won't report the problem as neatly.
As a workaround, a simple way to check the constraint you showed takes advantage of the fact that pointer conversions are implicit only when upcasting:
public class Test<T> where T : BaseClass
{
static T* enforcement_helper = 0;
static BaseClass* enforce_inheritance_constraint = enforcement_helper;
};
Depending on how new your compiler is, you may need to put those lines inside a special member function (destructor is good, because it's almost always processed).
But you should only check constraints in order to improve error messages (by causing the failure in a clearly commented section of code). C++ templates are duck typed, and they will work with any template parameters that provide the required operations. No formal "interface" is required.
I have a c++ class such as the following:
class some_class {
protected:
decide_later some_variable;
public:
void some_random_function();
};
void some_class::some_random_function() {
decide_later another_variable;
}
The problem is that I don't know what variable type some_variable will be until I create an instance of the class. What I want to do is something like the following:
some_class class_instance(std::string);
And that would set decide_later to use std::string (or int, or double, or whatever it is told to use). In addition, it would be great if I could use decide_later as a variable type later on in other functions that are members of the class. For example, in the function some_random_function().
I have tried using boost::any to do this, but it seems to only work for numeric types. Besides, I think it would be more efficient if I could actually set the actual variable type.
Is this possible?
You are looking for templates. Declare your class like:
template <typename T> class some_class {
protected:
T some_variable;
public:
void some_random_function() {
T another_variable;
}
};
and instantiate it with:
some_class<std::string> class_instance();
If you know the type statically when you create the instance, you should use C++ templates and make the type a template parameter.
If you know it only dynamically (i.e. based on user input), you can either branch then and instantiate the template with different type parameters, or you can go for a completely dynamical solution (like boost::any or equivalent).
However, I believe that if you can't do this with templates then there's something wrong in your program design. The idea of C++ static typing is that types are known at compile time. Normally in object-oriented design you would use polymorphism instead of weak typing.
Mixins and function templates are two different ways of providing a behavior to a wide set of types, as long as these types meet some requirements.
For example, let's assume that I want to write some code that allows me to save an object to a file, as long as this object provides a toString member function (this is a rather silly example, but bear with me). A first solution is to write a function template like the following:
template <typename T>
void toFile(T const & obj, std::string const & filename)
{
std::ofstream file(filename);
file << obj.toString() << '\n';
}
...
SomeClass o1;
toFile(o1, "foo.txt");
SomeOtherType o2;
toFile(o2, "bar.txt");
Another solution is to use a mixin, using CRTP:
template <typename Derived>
struct ToFile
{
void toFile(std::string const & filename) const
{
Derived * that = static_cast<Derived const *>(this);
std::ofstream file(filename);
file << that->toString() << '\n';
}
};
struct SomeClass : public ToFile<SomeClass>
{
void toString() const {...}
};
...
SomeClass o1;
o.toFile("foo.txt");
SomeOtherType o2;
o2.toFile("bar.txt");
What are the pros and cons of these two approaches? Is there a favored one, and if so, why?
The first approach is much more flexible, as it can be made to work with any type that provides any way to be converted to a std::string (this can be achieved using traits-classes) without the need to modify that type. Your second approach would always require modification of a type in order to add functionality.
Pro function templates: the coupling is looser. You don't need to derive from anything to get the functionality in a new class; in your example, you only implement the toString method and that's it. You can even use a limited form of duck typing, since the type of toString isn't specified.
Pro mixins: nothing, strictly; your requirement is for something that works with unrelated classes and mixins cause them to be become related.
Edit: Alright, due to the way the C++ type system works, the mixin solution will strictly produce unrelated classes. I'd go with the template function solution, though.
I would like to propose an alternative, often forgotten because it is a mix of duck-typing and interfaces, and very few languages propose this feat (note: very close to Go's take to interfaces actually).
// 1. Ask for a free function to exist:
void toString(std::string& buffer, SomeClass const& sc);
// 2. Create an interface that exposes this function
class ToString {
public:
virtual ~ToString() {}
virtual void toString(std::string& buffer) const = 0;
}; // class ToString
// 3. Create an adapter class (bit of magic)
template <typename T>
class ToStringT final: public ToString {
public:
ToStringT(T const& t): t(t) {}
virtual void toString(std::string& buffer) const override {
toString(buffer, t);
}
private:
T t; // note: for reference you need a reference wrapper
// I won't delve into this right now, suffice to say
// it's feasible and only require one template overload
// of toString.
}; // class ToStringT
// 4. Create an adapter maker
template <typename T>
ToStringT<T> toString(T const& t) { return std::move(ToStringT<T>(t)); }
And now ? Enjoy!
void print(ToString const& ts); // aka: the most important const
int main() {
SomeClass sc;
print(toString(sc));
};
The two stages is a bit heavyweight, however it gives an astonishing degree of functionality:
No hard-wiring data / interface (thanks to duck-typing)
Low-coupling (thanks to abstract classes)
And also easy integration:
You can write an "adapter" for an already existing interface, and migrate from an OO code base to a more agile one
You can write an "interface" for an already existing set of overloads, and migrate from a Generic code base to a more clustered one
Apart from the amount of boiler-plate, it's really amazing how you seamlessly pick advantages from both worlds.
A few thoughts I had while writing this question:
Arguments in favor of template functions:
A function can be overloaded, so third-party and built-in types can be handled.
Arguments in favor of mixins:
Homogeneous syntax: the added behavior is invoked like any other member functions. However, it is well known that the interface of a C++ class includes not only its public member functions but also the free functions that operates on instances of this type, so this is just an aesthetic improvement.
By adding a non-template base class to the mixins, we obtain an interface (in the Java/C# sense) that can be use to handle all objects providing the behavior. For example, if we make ToFile<T> inherits from FileWritable (declaring a pure virtual toFile member function), we can have a collection of FileWritable without having to resort to complicated heterogeneous data structures.
Regarding usage, I'd say that function templates are more idiomatic in C++.