I am a "C" programmer that knows just the tiniest bits of C++. I am having a look at some open source C++ code trying to understand some things that it is doing. I can work out most of it but sometimes there is syntax I don't recognise and I'd like to be able to "look up" the meaning of the syntax so I can read just enough to understand that bit of C++. But you can't just type a bunch of symbols into google - or whatever to find out the meaning in C++. Any suggestions of how I can do this in general?
The specific syntax I'm struggling with right now is the following:
void Blah<BOARD>::Generate(SgPoint p)
What is the significance of the <BOARD> in this context? What should I look up in order to understand it?
void Blah<BOARD>::Generate(SgPoint p)
Generate is a member function of a class template Blah .
BOARD is the name of the parameter.
Your class Blah could be like this :
template <typename BOARD>
class Blah
{
//...some code
void Generate(SgPoint p);
//...some more code
};
Blah is most likely a templated class, Generate is a method from this class and this is most likely the first line of the method definition.
Edit: Oh and BOARD is the template parameter (can be type or integral value).
This is the Generate method of the Blah class template specialized for template parameter BOARD.
In other words, what follows is the actual code that gets called when the Blah template is used to process an instance of class BOARD.
Other classes may get processed in a different way if separate specializations exist for them, or via the default non-specialized implementation of Generate, or not at all if there is no default and no specialization for them - in which case, an attempt to call that function will not compile.
There is a short introduction to the topic of template specialization here.
You run into C++ templates - very neat feature!
Related
I'm reading a book about how templates work, and I'm having difficulty understanding this explanation of templates.
It says
When the compiler sees the definition of a template, it does not generate code. It generates code only when we instantiate a specific instance of the template. The fact that code is generated only when we use a template (and not when we define it) affects how we organize our source code and when errors are detected...To generate an instantiation, the compiler needs to have the code that defines a function template or class template member function. As a result, unlike non-template code, headers for templates typically include definitions as well as declarations.
What exactly does it mean by "generate code"? I don't understand what is different when you compile function templates or class templates compared to regular functions or classes.
The compiler generates the code for the specific types given in the template class instantiation.
If you have for instance a template class declaration as
template<typename T>
class Foo
{
public:
T& bar()
{
return subject;
}
private:
T subject;
};
as soon you have for example the following instantiations
Foo<int> fooInt;
Foo<double> fooDouble;
these will effectively generate the same linkable code as you would have defined classes like
class FooInt
{
public:
int& bar()
{
return subject;
}
private:
int subject;
}
and
class FooDouble
{
public:
double& bar()
{
return subject;
}
private:
double subject;
}
and instantiate the variables like
FooInt fooInt;
FooDouble fooDouble;
Regarding the point that template definitions (don't confuse with declarations regardless of templates) need to be seen with the header (included) files, it's pretty clear why:
The compiler can't generate this code without seeing the definition. It can refer to a matching instantiation that appeared first at linking stage though.
What does a non-template member function have that allows for it to
be defined outside of the header that a template function doesn't
have?
The declaration of a non-template class/member/function gives a predefined entry point for the linker. The definition can be drawn from a single implementation seen in a compiled object file (== .cpp == compilation unit).
In contrast the declaration of a templated class/member/function might be instantiated from arbitrary compilation units given the same or varying template parameters. The definition for these template parameters need's to be seen at least once. It can be either generic or specialized.
Note that you can specialize template implementations for particular types anyway (included with the header or at a specific compilation unit).
If you would provide a specialization for your template class in one of your compilation units, and don't use your template class with types other than specialized, that also should suffice for linking it all together.
I hope this sample helps clarifying what's the difference and efforts done from the compiler.
A template is a pattern for creating code. When the compiler sees the definition of a template it makes notes about that pattern. When it sees a use of that template it digs out its notes, figures out how to apply the pattern at the point where it's being used, and generates code according to the pattern.
What is the compiler suppose to do when it sees a template? Generate all the machine code for all possible data types - ints, doubles, float, strings, ... Could take a lot of time. Or just be a little lazy and generate the machine code for what it requires.
I guess the latter option is the better solution and gets the job done.
The main point here is that compiler does not treat a template definition until it meets a certain instance of the template. (Then it can proceed, I guess, like it have a usual class, which is a specific case of the template class, with fixed template parameters.)
The direct answer to your question is: Compiler generates machine code from users c++ code, I think this is wat is meant here by word "generate code".
The template declaration must be in header file because when compiler compiles some source, which use template it HAVE only header file (included in source with #include macro), but it NEED whole template definition. So logical conclusion is that template definition must be in header.
When you create a function and compile it, the compiler generates code for it. Many compilers will not generate code for static functions that are not used.
If you create a templated function and nothing uses the template (such as std::sort), the code for the function will not be generated.
Remember, templates are like stencils. The templates tell how to generate a class or function using the given template parameters. If the stencil is not used, nothing is generated.
Consider also that the compiler doesn't know how to implement or use the template until it sees all the template parameters resolved.
It won't straight away generate code. Only generates the class or template code when it comes across an instantiation of that template. That is, if you are actually creating an object of that template definition.
In essence, templates allow you abstract away from types. If you need two instantiations of the template class for example for an int and a double the compiler will literally create two of these classes for you when you need them. That is what makes templates so powerful.
Your C++ is read by the compiler and turned into assembly code, before being turned in machine code.
Templates are designed to allow generic programming. If your code doesn't use your template at all, the compiler won't generate the assembly code associated. The more data types you associate your template with in your program, the more assembly code it will generate.
I am using a C++ class which is templated.
I instantiate two different templated version of this class:
ExampleClass<ParamType1> obj1;
ExampleClass<ParamType2> obj2;
So that I have two objects which are the same class, but with different template parameters.
I now want to be able to define a function (extremely simplified example!) that can take either obj1 or obj2 as a parameter:
int func(ExampleClassXXX obj_param)
{
return obj_param.member_operation();
}
So that I can call either func(obj1) or func(obj2.
Is this something that is possible, and if so, what is the syntax needed for the function definition to specify the obj_param parameter is "an instance of ExampleClass created with any template parameters"?
The answer to this question sort of covers the case that is one step more general - having "obj_param" be any type. Most of the details are missing from the text of that answer, it is only when you click on the "live demo" that you see they are instantiating a templated struct to be able to pass in the generic parameter, which is pretty ugly.
It seems like this should be a common thing to want to do, but Googling has failed me so far (searching for "passing templated object as function parameter")
Note that
ExampleClass<ParamType1>
and
ExampleClass<ParamType2>
are basically two different classes for the language.
You have two possibilities, in my opinion, the first being:
template<typename ParamType>
int func(ExampleClass<ParamType> obj_param){}
The second possibility is to give to ExampleClass a non-templated public base class (basically implementing type erasure) like so
template<typename T>
class ExampleClass : public ExampleClassBase{};
and then re-write the function as
int func(ExampleClassBase& obj_param){}
but you will not be able to pass by value in this case because of object slicing issues.
The template function forces you to implement the function in a header file if you want to keep it as general as possible, the non-templated base class forces you to pay for virtual function call.
Edit: as per Alan Birtles comment, if you know already all the types you will instantiate ExampleClass with you can implement each version of the function in a cpp file.
So that I have two objects which are the same class, but with different template parameters.
A contradiction right there. If the arguments are different, this is not the same class. A template is not a class, it's a mold. If you pour two different metals into it, you'd get two very different objects, despite the similar shape. They'd have different mass and density, possibly different electromagnetic properties, and so forth. A bit tangential, but it's important to differentiate the template from the things it produces, those are not the same.
This is why different specializations produced from the same template are considered different classes. They are not related under the type system, and so no function can automatically treat them as the same thing. You could create a function template, and use it to generate functions for each distinct specialization, but those too would be different functions.
If you have a part that's common to all specializations, you could refactor it out into a base class (proper class, not a class template), and have a function that accepts that.
In page 671 of his new book Mr Stroustrup wrote the following sentence:
Note that there is no requirement that different arguments for the
same template parameter should be related by inheritance.
I can understand what the author wrote, but I can't understand the reason why he inserted this comment in the text. I think I'm missing something here, but I don't know exactly what.
When introducing the concept of templates, he tries to make clear that its not some kind of polymoprhism.
Before template were invented and added to C++ you could write generic code only using inheritance (or multilple inheritance).
Another concept that Mr.Stroustrup certainly want the reader not to confuse with templates is interfaces. In the java comunity for example this is a very popular technique and many books abot OOP explain this concept. Interfaces allow you to use some kind of generic code with a class, at the condition that the class is defined to implement (not inherit) a specific interface. All classes using the interface must be related to it. It's not strictly speaking inheritance, but it's a kind of substitute to multiple inheritance.
Templates can be used with any object or class without its type being related in advance to anything in common.
The answer is simple if we look at the use case of templates from the perspective of someone who is totally new to the concept of templates.
int i;
double d;
char c;
print(&i); //prints an integer
print(&d); //prints a double
print(&c); //prints a char
From the perspective of someone who does not understand C++ templates, he/she would assume that the prototype of print looks something like this.
print(SomeBaseType* pdata);
OR
print(void* pdata);
However, what happens with templates is with a function template such as
template <typename T>
print(T* pdata);
for the above use case, the compiler generates three functions during compile-time
print(int* pdata);
print(double* pdata);
print(char* pdata);
and through function overload resolution, the right function gets called.
Thank you for reading.
Disclaimer: A print function might not be the best example.
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.
Can someone give a hint how does compiler process expressions such as
class DerivedA: public ParentTemplateClass<DerivedA>{
}
For mee it looks like:
this boy's father is a "son" of this boy
I mean it's not obvious for me how "parsing" of the class DerivedA can be completed WITHOUT knowing the exactly "description" of parent class. Seems' it can not. So parent class must be processed before children, but in such situation parent depends on children..and I'm stuck there.
Yeah there some articles on the web which describe usage of such thing, e.g. an article about Curiously Recurring Template Pattern (
http://en.wikibooks.org/wiki/More_C++_Idioms/Curiously_Recurring_Template_Pattern) but that's not some kind of standart or smth near. There must be clear behaviour description such as operations ordering isn't it?
ANSWERED:
Thnx to everyone. Yeah forward decl analogy seems legit for me to stop damaging my brain. Templates are still state of art for me cause of its hidden sublanguage nature and i cant just g++ -E :)
After your code says class DerivedA, the symbol DerviedA is declared. At the point it can be used as a template parameter. C++ compilers do several passes on the code, so at that point in parsing the compiler will "believe" that your intention was correct and that it will eventually get the definition of that class (when it is about to instantiate the template, i.e. you actually use that type). If not, it will complain at that point. A similar thing happens if you used a forward declared class in a declaration but didn't provide a definition before using it.
At the point at which the template is instantiated, DerivedA is incomplete; it has been declared, but not fully defined. Incomplete types can be used in various ways - for example, you can declare pointers or references to them, declare functions with them as return or parameter types, and a few other things. You can't create objects, inherit from them, access their members, or in general do anything that requires more information than just the class name.
As long as the class template only does these things, there is no problem.
I think to understand how this could work, you need too understand more about C++ templates in general, than just the Curiously Recurring Template Pattern. Someone else can probably answer this better than me, but I know that C++ can't fully parse a template class definition by itself. It instantiates the template each time it is used in the code. If each class was in a separate include file, think of it like this:
#include "ParentTemplateClass.h" // C++ initially validates the template class definition's syntax.
#include "DerivedA.h" // First use of ParentTemplateClass -
// at this point it becomes fully instantiated.
The C++ parser will initially validate the template's syntax when it sees the template definition. Then, when the template is used as a base of DerivedA, the parsing continues and the template is fully instantiated. This is, of course, a simplified view of the parsing that the C++ compiler will do, and I'm sure the details vary by compiler. See also http://womble.decadent.org.uk/c++/template-faq.html#disambiguation.