What Is The Purpose Of A Template C++
Using Templates and Generics in C
Generics are syntax components of a programming language that can exist reused for different types of objects. Typically, generics take the form classes or functions, which take type(south) as a parameter. Generics are also usually referred to as templates, and in C++ are officially chosen templates. Typically, programming languages which lack generics or templates accept received criticism. Having the ability to share procedural code between types greatly improves quality and development. This article describes a few techniques and methods to accomplish template-like functionality in pure C.
What is a blazon?
Generics and templates allow types to use the aforementioned code. But, what really constitutes a "type" in a linguistic communication like C? Unlike other object-oriented programming languages, C does non have a native concept of construction and destruction of objects. There is also no native concept of inheritance built into the language. C views types as sections of retentivity with a particular known format of their data. Officially, types are broken downward into two categories, scalar and aggregate types.
A scalar blazon holds only one data item, such as int or char*. These are most often integer or pointer types. Amass types agree one or more data values, such as any array or struct. The type void* represents a special pointer type that can point to whatsoever type, scalar or aggregate. In fact, void* tin can sometimes be used as a course of generic lawmaking. Quite a few functions in string.h use void* for reading and writing memory chunks of different sizes.
Therefore, a type in C must have:
- A known size
- A known format
Two types may have the same size, but non the aforementioned format. Such every bit, on virtually platforms, float and int. They usually take the same size, and as such, sizeof(int) == sizeof(bladder) holds truthful. Yet, they have an entirely dissimilar format, and thus will behave differently when called with particular functions.
Static Templates
The main type of templates that can be implemented in C are static templates. Static templates are created at compile fourth dimension and do not perform runtime checks on sizes, because they shift that responsibility to the compiler. Static templates used in C are similar to the templates from the C++ language, because they depend on the actual blazon members, such every bit in the example of a struct. In C, the just native means of creating static templates are through the apply of macros.
Note: The use of the discussion 'static' just ways 'at compile time'. Information technology is not related to the C keyword static , which means a role has internal linkage
To begin, allow'southward observe the simplest course of a static template, a definition macro:
#define DEF(type, name, val) type name = val
DEF(int, foo, 5);
// Then used as normal
printf("%d", foo); The DEF macro described in a higher place can work with any type which can be initialized via the = operator. It could also work by doing:
DEF(const char*, txt, "foo"); This template allows the code needed to ascertain variables with basic blazon to exist generalized and abstracted. The goal is to brand code sharable and similar betwixt types. However, this example is footling in the sense it provides very little simplification over simply writing out the argument. The existent power comes from code that performs more circuitous tasks.
Foreach
In C, for loops can outcome in a lot of code existence very type specific, leading to redundant code, and huge source files. With the assist of static templates in the form of macros, we can make for looping much smoother in C. Starting time, consider a standard for loop:
for (int i = 0; i < 10; i++) {
printf("%d", i); // ... //
} At that place are iv distinct syntax components. The initialization of the variable, the termination condition, the incremental step, and finally the actual block of code to be executed upon each increment in the loop. Given those four elements, we tin can construct a macro which acts as a foreach loop.
#define FOREACH(type, start, terminate, fn) \
for (type _foreach_var = beginning; _foreach_var != stop; _foreach_var++) { \
fn(_foreach_var); \
} This template works for primitive type ranges, where in that location is a known type, a start value, an end value, and a desired function to be applied for each member of the range. The name_foreach_var is chosen to purposefully decrease the possibility of collision with one of the macro's arguments. Exercise note, fn does not have to be a part. You lot could, in this case, pass in a macro for fn, which is also called a college order macro:
#define PRINT_INT(n) printf("%d", northward)
// apply FOREACH
FOREACH(int, 0, 5, PRINT_INT) For loop templates can also be used on loops that iterate over the contents of an amass blazon, such equally an assortment. Using aggregate types tin can sometimes exist even more direct forward with macros, because we can derive more information from an aggregate type than a scalar blazon. Using the sizeof operator, we can decide the number of elements in an array.
long nums[iv];
const size_t nums_count = sizeof(nums) / sizeof(nums[0]); printf("%zu\northward", nums_count);
// 4 The sizeof operator always takes the size of a value in bytes. This means passing an assortment will evaluate to the total size of that array. This does not piece of work with pointer types, as the size of any arrow will ever be the same as sizeof(void*). This information that tin can be inferred from an array can be used to make a powerful "foreach" template:
#define FOREACH(arr, fn) \
for (size_t _ind = 0;
_ind < sizeof(arr) / sizeof(arr[0]);
_ind++) { \
fn(arr[_ind]); \
} In the FOREACH macro above, the simply two arguments required are the assortment itself, arr, and some callable to apply for each element in arr. The size_t type tin exist used to access any assortment chemical element. We don't need to also pass in the blazon of arr, because we don't need it, we can allow fn handle information technology.
Functions
Static templates tin too be implemented in C to embody entire functions. This arroyo to generics and templating is needed when the desired beliefs is more complex than what can be captured in a loop-oriented template. Typically in C, parameters taking the form of multiple unlike types volition exist given the type void*, which another size_t parameter representing the size of the memory the void* points to. This style of function definition is used in the standard library, such as with the functions memcpy and memset.
An issue with using void* is the lack of type checking. Whatsoever address of whatever type in C can exist stored in void*, such as
int due south = 3;
char mes[fifty];
long b = 6754333; void* ps = &s;
void* pmes = mes;
void* pb = &b;
Those are all valid definitions. There is no fashion for the compiler to interpret an incorrect type is being passed to a void* intended for a different blazon. Therefore, functional templates provide a way to limit the scope of types accepted into generic functions. For a start, permit's wait at an example of comparing two aggregate types by a particular field's value for equality:
The in a higher place template is a macro that produces a office definition everytime it is chosen. This function takes ii const pointers of the specified blazon, and returns the result of comparison field. The name of the part produced has the name of the type appended to the cease of information technology. We demand each definition of this equality template part to take information technology'due south own proper noun, considering C does not allow functions to have the same name yet conflicting types. This means that, with this template, doing
FIELD_EQ(point_t, x)
FIELD_EQ(foo_t, ten) Would actually produce FIELD_EQ_point_t and FIELD_EQ_foo_t respectively. The advantage here is, we tin create the aforementioned part for multiple types without explicitly writing out those functions multiple times. Here is an instance of both using the functional template and calling the produced function:
typedef struct {
int x;
int y;
} point_t; FIELD_EQ(point_t, ten) int main(void) {
point_t f1 = {3, 5};
point_t f2 = {3, three};
printf("result is %d\n", FIELD_EQ_point_t(&f1, &f2));
render 0;
}
This blueprint of function product tin be used to create identical C APIs between dissimilar types.
Structures
In C, structures, chosen "structs" for short, are aggregate types that can incorporate heterogeneous, named fields of information. In comparing to other languages, a struct is like an object with no methods, no constructor, and no destructor. Structs are chunks of formatted data composed of multiple scalar types. Structs are dissimilar than objects in other languages because there is no builtin fashion of achieving polymorphism. Nor is in that location a native way to achieve inheritance, such as in the desired case of a parent struct and child struct.
Interpreted programming languages, specifically Python, apply an object "caput" approach. This means that, any struct that is considered an "object" of the language, has a special collection of fields in the get-go of it'south definition, that hold information related to the structs identity. This allows all of the structs to be cast to a common base struct type, every bit long every bit they bear these fields before any other specific fields are defined. The Python C API accomplishes this with a macro chosen PyObject_HEAD. This macro carries fields that identify the type of the struct, it'southward size, and more.
A more basic instance would expect similar the post-obit:
In the above, obj_t is the base of operations struct of all other obj_*_t related structs. It is defined purely with the macro OBJECT_HEAD, holding the type information about the struct. This macro is a template, any other struct with OBJECT_HEAD equally part of it's definition will be able to be cast to obj_t. This tin can be seen in the struct type obj_int_t. The creation of struct types which can be cast to obj_t can be simplfied with a higher order macro template:
#define OBJECT_START(name) \
struct name { \
OBJECT_HEAD; #define OBJECT_END(proper noun) }; \
typedef struct name name
These two macros, OBJECT_START and OBJECT_END allow more standard type definitions of template structs. They guarantee whatever defining statements between the first and end macro will class a obj_t compatible blazon. More than so, it ensures the name of the blazon volition exist under the struct <name> and <name> namespaces.
Conclusion
Overall, implementing templates in C tin can brand C code more than readable, less redundant, and less prone to errors. It allows efficient development without the demand to contain or switch to C++ or languages with builtin template systems, if desired. Using generics and templates in C tin can also make programs more blazon safe, and foreclose improper access of retentivity.
What Is The Purpose Of A Template C++,
Source: https://levelup.gitconnected.com/using-templates-and-generics-in-c-968da223154d
Posted by: balesdeally70.blogspot.com

0 Response to "What Is The Purpose Of A Template C++"
Post a Comment