Generic programming: Difference between revisions

Content deleted Content added
Tags: Mobile edit Mobile web edit
 
(6 intermediate revisions by 3 users not shown)
Line 213:
 
=====Technical overview=====
There are many kinds of templates, the most common being function templates and class templates. A ''function template'' is a pattern for creating ordinary functions based upon the parameterizing types supplied when instantiated. For example, the C++ Standard Template Library contains the function template <code>std::max(x, y)</code> that creates functions that return either ''x'' or ''y,'' whichever is larger. <code>max()</code> could be defined like this:
 
<syntaxhighlight lang="cpp">
template <typename T>
[[nodiscard]]
constexpr T max(T x, T y) noexcept {
return x < y ? y : x;
}
Line 231 ⟶ 232:
 
<syntaxhighlight lang="cpp">
[[nodiscard]]
constexpr int max(int x, int y) noexcept {
return x < y ? y : x;
}
</syntaxhighlight>
 
This works whether the arguments <code>x</code> and <code>y</code> are integers, strings, or any other type for which the expression <code>x &lt;< y</code> is sensible, or more specifically, for any type for which <code>operator&lt;</code> is defined. Common inheritance is not needed for the set of types that can be used, and so it is very similar to [[Duck typing#Templates or generic types|duck typing]]. A program defining a custom data type can use [[operator overloading]] to define the meaning of <code>&lt;<</code> for that type, thus allowing its use with the <code>std::max()</code> function template. While this may seem a minor benefit in this isolated example, in the context of a comprehensive library like the STL it allows the programmer to get extensive functionality for a new data type, just by defining a few operators for it. Merely defining <code>&lt;<</code> allows a type to be used with the standard <code>std::sort()</code>, <code>std::stable_sort()</code>, and <code>std::binary_search()</code> algorithms or to be put inside data structures such as <code>std::set</code>s (equivalent to <code>TreeSet</code>, [[heap (programming)|heap]]s, and [[associative array]]s.
 
C++ templates are completely [[type safe]] at compile time. As a demonstration, the standard type <code>std::complex</code> does not define the <code>&lt;<</code> operator, because there is no strict order on [[complex number]]s. Therefore, <code>std::max(x, y)</code> will fail with a compile error, if ''x'' and ''y'' are <code>complex</code> values. Likewise, other templates that rely on <code>&lt;<</code> cannot be applied to <code>complex</code> data unless a comparison (in the form of a functor or function) is provided. E.g.:For Ainstance, <code>std::complex</code> cannot be used as key for a <code>std::map</code> (equivalent to <code>TreeMap</code>) unless a comparison is provided. Unfortunately, compilers historically generate somewhat esoteric, long, and unhelpful error messages for this sort of error. Ensuring that a certain object adheres to a [[protocol (computer science)|method protocol]] can alleviate this issue. Languages which use <code>std::compare</code> instead of <code>&lt;<</code> can also use <code>std::complex</code> values as keys.
 
Another kind of template, a ''class template,'', extends the same concept to classes. A class template specialization is a class. Class templates are often used to make generic containers. For example, the STL has a [[doubly linked list]] container, <code>std::list</code> (equivalent to <code>LinkedList</code>). To make a linked list of integers, one writes <code>std::list&lt;<int&gt;></code>. A list of strings is denoted <code>std::list&lt;<std::string&gt;></code>. A <code>std::list</code> has a set of standard functions associated with it, that work for any compatible parameterizing types.
 
[[C++20]] introduces constraining template types using [[Concepts (C++)|concepts]]. Constraining the <code>max()</code> could look something like this:
 
<syntaxhighlight lang="cpp">
// in typename declaration:
template <std::totally_ordered T>
[[nodiscard]]
constexpr T max(T x, T y) noexcept {
return x < y ? y : x;
}
 
// in requires clause:
template <typename T>
requires std::totally_ordered<T>
[[nodiscard]]
constexpr T max(T x, T y) noexcept {
return x < y ? y : x;
}
</syntaxhighlight>
 
=====Template specialization=====
Line 690 ⟶ 711:
[[VHDL]], being derived from Ada, also has generic abilities.<ref>https://www.ics.uci.edu/~jmoorkan/vhdlref/generics.html VHDL Reference</ref>
 
[[C (programming language)|C]] has a feature called "type-generic expressions" using the {{c-lang|_Generic}} keyword:<ref name="N1516">[https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1516.pdf WG14 N1516 Committee Draft — October 4, 2010]</ref> This feature gives cC [[function overloading]] capabilities, but is not related to generic programming. Generic programming can be achieved by using the preprocessor to define the generic code, with macro expansion taking the role of ''instantiation''. Sometimes, the non-standard extension "statement expressions" is used to simulate function -like behaviour for generic code:
<syntaxhighlight lang="c">
#define max(a,b) \
Line 696 ⟶ 717:
typeof (b) _b = (b); \
_a > _b ? _a : _b; })</syntaxhighlight>
 
The keyword <code>_Generic</code> is used in C preprocessor macros to automatically match the type of its parameter.
 
<syntaxhighlight lang="c">
#include <stdio.h>
 
#define type_of(x) _Generic((x), \
int: "int", \
float: "float", \
double: "double", \
char*: "string", \
default: "unknown")
 
int main(int argc, char* argv[]) {
printf("%s\n", type_of(42));
printf("%s\n", type_of(3.14f));
printf("%s\n", type_of(2.718));
printf("%s\n", type_of("hello"));
printf("%s\n", type_of((void *)0));
return 0;
}
</syntaxhighlight>
 
==See also==
Line 743 ⟶ 786:
* [[Free Pascal]]: [https://www.freepascal.org/docs-html/ref/refch8.html Free Pascal Reference guide Chapter 8: Generics], Michaël Van Canneyt, 2007
* Delphi for Win32: [https://sjrd.developpez.com/delphi/tutoriel/generics/ Generics with Delphi 2009 Win32], Sébastien DOERAENE, 2008
* Delphi for .NET: [https://www.felix-colibri.com/papers/oop_components/delphi_generics_tutorial/delphi_generics_tutorial.html Delphi Generics] {{Webarchive|url=https://web.archive.org/web/20230114100915/http://www.felix-colibri.com/papers/oop_components/delphi_generics_tutorial/delphi_generics_tutorial.html |date=14 January 2023 }}, Felix COLIBRI, 2008
 
;Eiffel