I need to bind a simple template method to LUA, something like
void addComponent<T>(IComponent*);
I'm using tolua to do the bindings but it doesn't support class/method templates (tolua++ supports class templates but not the method ones :) ). Is there any way to bind this method manually?
Thanks in advance.
C++ templates do not actually exist outside of the compiler. Instantiations of templates exist, but the templates themselves are purely a compile-time construct.
There is no function called void addComponent<T>(IComponent*); There is a function called, void addComponent<int>(IComponent*) or void addComponent<float>(IComponent*) or for any particular type you want. But templates are not real functions.
You can bind an instantiation of a template, which is a concrete function. This works just like binding any free function in toLua. The name of an instantiation would be, addComponent<TypeName> where TypeName is the name of the concrete type you want to instantiate it with.
To put it another way, you can't bind the concept of addComponent which is defined for any type. You can bind any actual addComponent that is defined for a specific type.
Related
I have an abstract class Primitive, which has some pure abstract functions.
Then i have a tree implementation with templates:
template<typename PrimitiveT>
class PrimitiveTree {
...
}
// explicit instantiation
template class PrimitiveTree<Project::Primitive>; // abstract
template class PrimitiveTree<SimpleTrianglePrimitive>; // implementation
which is used in another file as
PrimitiveTree<Primitive> *ptree;
With this code I get error C2259: 'Project::Primitive': cannot instantiate abstract class. When I remove the instantiation of the abstract class, I get linker errors that the corresponding symbol for PrimitiveTree<Primitive> is not found in the object file.
A similiar class with the methods inside the header file doesn't have these problems, when used with Primitive as template argument.
How do i need to instantiate the template class, such that the neccessary symbols are added to the object file, even when the template argument is an abstract class?
You need to ensure that the template PrimitiveTree<PrimitiveT> does not rely on PrimitiveT (the template parameter) being instantiable - in other words, not being abstract. One property of an abstract class is that it cannot be instantiated.
This means your PrimitiveTree template must only work with pointers or references to PrimitiveT, and never instantiate an actual instance PrimitiveT in any way. This means it is not possible to declare PrimitiveT as a data member (static or non-static). It is not possible to pass a PrimitiveT by value. It is also not possible dynamically create any instances with a new expression (e.g. some_pointer = new PrimitiveT[5]) since a new expression relies on the type being instantiable (i.e. not abstract).
Everywhere where PrimitiveT is used must be either a reference or a pointer. Defining or declaring a pointer or reference to PrimitiveT, or passing a reference/pointer as a function argument does not rely on PrimitiveT being instantiable.
If you write ANY code for PrimitiveTree that relies on PrimitiveT being instantiated, then the implementation cannot instantiate the template.
The "similar class" in another header file probably does not rely on Primitive being instantiable, since it follows guidelines like the above.
In C++ for a template T variable for a class.
What would it's binding time be?
I'm thinking compile time because it would need to know what value is being passed to it before binding it to a value/address.
Yes. You could think of templates as "class factories", the result of using a template is a class that has been specialized for the specific types you use in the template. So this is all compile-time specialization.
I have a large class which basically handles one buffer of variable (numeric) datatype. So it seems a good choice to use a class template with this datatype as the only parameter. I'm not experienced in C++ and I wonder/worry a bit about the "footprint" such a template makes in my code.
There are three implications of templates which in my (C++ unexperienced) eyes are not necessary and make code ugly. I tried to avoid them, but neither did I find a good example how to do it nor did I manage to find it out by myself.
So the goal of this question is: Can you either confirm the following statements or give a counterexample?
When using a class template, all class methods have to go into the header file. Even if they have no templated type in their interface or implementation.
When using a static method or member of the class, I always have to specify a template parameter (MyClass< double > :: MY_STATIC), even if the templatization does not affect any of the static properties of the class.
When using the class as a parameter for a function, I always have to give a template parameter, even when this function does not access any of the templated members? (function myFunc(MyClass< double> & myClass){ do something } )
As a general rule, don't have functions/data members in a template class which does not use the template parameters. Have a base class, put all non-template related things there, your template class should derive from it.
To answer your questions:
yes, everywhere where you need to instantiate the template, you need to see the full definition of the class and it's functions
yep, but put that into the base class
yes, see above
EDIT: One of the reasons to move to base class is code bloating (this expression actually exist, you can google it for more info): If you don't move the template unrelated code to a base class, the very same template independent code will be copied for all instantiation of your template, which means a lot of unnecessary code. If you put it to a base class, you will only have this code once.
Yes. On the plus side, the code is only generated when the metod is actually used for the specialization.
Yes. However, there is no (other then design choice) need for a static method to be a memeber of the templated class if it has no use for the templated parameter.
Yes. The size and memory layout of the structure is determined by the template parameter.
Suppose a construct like this:
class Interface
{
public:
template <typename T>
virtual void reportOperationError(T code , std::string message) = 0;
};
i don't understand the use case for this thing, in which case it is useful, and how?
In case you wonder, I haven't seen this code anywhere, just want to understand if this could have some particular use
Templated member functions cannot be virtual... Each instantiation of the function will add another entry to the virtual table, and the compiler will have to go over all of the code in order to create the vtable. Therefore, regardless of it being useful or not, it's just not legal C++.
This isn't legal in C++. Member function templates cannot be virtual because the size of the VTable would be dependent on instantiations in other translation units which would make it very very hard for compiler implementers.
This would ruin the whole point of C++ compilation model, that is, separate compilation. A C++ translation Unit (AKA source file) must be self-sufficient to be compiled. If the member function tamplates are allowed, this gets nearly impossible
It's not possible to make virtual member function a template. This code will not compile, regardless of its potential utility.
Is it possible to specifiy a template as a member but not know all the details? Or rather how can I work around this.
Example doesn't work but might show you what I'm trying to achieve.
template<typename T>
struct Foo {
///blah...
};
struct Bar {
Foo* m_foo;
};
Bar in this case is a base class, and depending on the derived classes I wont know the full details of Foo
You can either make Bar a template class as well so it can pass that template argument along to Foo, or else you can make all the Foo<T> variations inherit from a common interface (in C++, an interface is just an abstract class with no implementation, all members are pure virtual functions) and then Bar can point to that interface.
The first way is better if Bar is just going to provide some functionality which will be reused by a bunch of derived classes.
The second way is better if descendants of Bar are going to be used polymorphically.
The code you have above won't work, since whenever you use a C++ template you must specify what it's arguments are. If you want to store a Foo of an unknown type, you can do so by parameterizing Bar over some type (for example, making it a template with type argument T), then having Bar store a Foo. This contrasts with other languages like Java where code like what you have outlined above is legal because templates work differently in C++. In particular, Java-style genetics just compile down to one concrete representation, then use runtime checks to verify that they're being used properly. C++ template instantiations all end up getting compiled down into separate code, and so the compiler has to be able to infer at compile-time what the argument types are (so it knows what code to generate).