Ch15: Generic Programming: Concepts, Templates, and Type Erasure

中文(简体)

1. Why This Chapter Exists

Chapter 4 answered “what is a vector” with ::fast_io::vector<int>, and never said where the <int> came from. Ch6.6 showed overload resolution picking between add(int, int) and add(double, double), and stopped where overloading stops helping: the moment the bodies are identical and only the type differs.

That moment is where generic programming begins. Its idea is not “fill in a type”; it is write the algorithm once, state what it needs, and let the compiler check that statement. Four tools do the work, and they are the four halves of this chapter:

This chapter has one enemy: bloat. Every distinct template argument produces a full copy of everything the template touches, and a program that instantiates the same logic a thousand times is a slow-to-compile, huge binary. So the chapter teaches templates and, in the same breath, the discipline of keeping them small: concepts to sharpen them, detemplatization to shrink them, and type erasure to hide them behind one type.

2. The One-Sentence Summary of Each Idea

Idea One sentence Subchapter
type trait A compile-time fact about a type, as a bool or as another type. Ch15.1
template definition A declaration with a parameter list; the compiler writes one copy per argument. Ch15.2
concept A named list of requirements the compiler checks before it instantiates; used to classify a type, not to build a dispatch. Ch15.3
non-type parameter A template argument that is a value, not a type. Ch15.4
deduction The compiler writing the <...> for you, from the arguments. Ch15.5
parameter pack Zero or more template arguments, consumed by a fold or by a template for. Ch15.6
template for A loop the compiler unrolls at compile time, one iteration per element. Ch15.7
if constexpr An if whose unselected branch is thrown away, not compiled. Ch15.8
detemplatization Move everything that does not touch the template argument out of the template. Ch15.9
type erasure One non-template type that can hold values of many types, with no inheritance. Ch15.10
print/scan support A tag variable and a concept: how fast_io's generic printing finds your type. Ch15.11

3. The Running Example

One tiny type follows us through the chapter: a colour with three 8-bit channels and a name.


struct rgb
{
	::std::uint_least8_t r{}, g{}, b{};

	[[nodiscard]] ::std::string_view name() const noexcept
	{
		return "rgb";
	}
};

It is small enough to print in the middle of a page, it has a member function to constrain, fields to compare, and an obvious textual form (7,128,255) to scan back in. The last page of the chapter teaches fast_io to print and scan exactly this type.

4. Conventions Used in This Chapter

5. What You Should Already Know

6. Contents