Other meanings of Generic programming
PROGRAMMING PARADIGMS
Generic programming is a programming paradigm for writing algorithms and data structures independently of specific data types. A generic component describes the operations it requires—such as comparison, iteration, or arithmetic—and can then work with many concrete types, provided those types satisfy the requirements.
Generic programming separates an algorithm’s logic from the particular types on which it operates. A generic sorting routine, for example, need not know whether it receives integers, strings, or records; it needs only access to an ordering operation. This approach is often called parametric polymorphism when one piece of code is uniformly parameterized by types, while ad hoc polymorphism selects type-specific implementations through overloading or type classes. The distinction is practical rather than absolute: languages frequently combine both techniques. Generic programming therefore concerns more than reusable syntax; it expresses relationships among data types, operations, and algorithmic requirements.
Generic components may be checked when they are declared, when they are instantiated, or at run time, depending on the language. Strong constraints can make errors easier to diagnose, while weaker constraints can permit broader reuse. The central goal is to make abstraction preserve useful type information rather than replacing every value with an undifferentiated universal representation.
1 3Languages implement generic programming through several distinct mechanisms. C++ templates generate or specialize code from type parameters, and the C++ standard library organizes many algorithms around requirements on iterators, ranges, and callable objects.1 Ada uses generic units that can be instantiated with types, values, and subprograms, making genericity an explicit program-library feature. Java generic classes and methods retain compile-time type relationships but normally implement them through type erasure, so many type arguments do not exist at run time.2
Rust combines type parameters with trait bounds, which state that a type supports named operations or behavior.4 Haskell expresses a related idea through type classes: a polymorphic function can require that its type belong to classes such as Eq or Ord.5 These mechanisms differ in syntax, compilation, and run-time behavior, but all make an interface of required capabilities central to reuse.
Generic programming is especially influential in library design because algorithms can be written against capabilities instead of inheritance hierarchies. The Standard Template Library, incorporated into C++, demonstrated how containers, iterators, and algorithms could be composed without forcing every data structure into one class tree. Its style favors small, interoperable abstractions: an algorithm can operate on any type whose interface meets its documented requirements.
Compilation strategies create different trade-offs. C++ and Rust commonly specialize generic code for concrete types, potentially enabling inlining and avoiding dynamic dispatch, though repeated instantiations can increase compile time and executable size.1 Java’s erased generics generally reduce such code duplication but restrict some operations involving type parameters at run time.2 Generic designs can also expose semantic assumptions—such as whether an ordering is consistent or whether copying is inexpensive—that a type signature alone may not capture. Good libraries document these informal contracts.
The hardest part of generic programming is often specifying the boundary of valid types, not writing the reusable algorithm. A type may provide a syntactically suitable operation while violating a semantic requirement: a comparator might not define a consistent ordering, or a hash function might disagree with equality. Modern constraint systems, including C++ concepts and Rust traits, make some requirements explicit, but laws and performance expectations can remain documentation-level contracts.1 4
Genericity also extends beyond ordinary type parameters. A component may be parameterized by a value, a memory policy, an execution strategy, or a user-supplied operation; Ada generics notably support formal subprogram parameters.3 In functional programming, higher-kinded abstractions can describe constructors such as lists or streams rather than only completed types. Conversely, excessive generality may make interfaces obscure, diagnostics difficult, or generated code expensive. The most durable designs usually discover a small, stable set of operations shared by genuinely related types.
Modern generic programming grew from efforts to make reusable software libraries independent of representation and machine-specific types. Ada made generic program units part of a standardized language design, while work associated with Alexander Stepanov and the C++ library community developed the algorithm-and-iterator style that became foundational to the STL. Later languages broadened the design space through type classes, bounded polymorphism, traits, and explicit concepts. These traditions are related but not identical: generic programming is a design principle, whereas templates, traits, and type classes are language mechanisms that can support it.
The paradigm now appears in systems software, numerical libraries, compilers, database frameworks, and application code. Its influence is visible whenever a library promises one implementation for many types while stating the operations or laws those types must satisfy. The continuing challenge is balancing expressive abstraction with understandable interfaces, predictable performance, and useful compiler feedback.
1 3Terminology varies across languages: a feature called a template, generic, trait, or type class may provide overlapping but not identical forms of generic programming.
Help improve the encyclopedia. Reports go straight to the site manager.