Guidelines for Teaching C++

Version PR_0.0.20

SG20 (ISO C++ Study Group on Education)

1 Obtaining This Document: The Most Recent Version and Alternate Formats

The most recent version of this document is available as an online HTML document at: https://cplusplus.github.io/SG20/latest/.

The version of the document that you are currently reading is available in the following formats:

  1. online (HTML) format as a single large HTML document: https://cplusplus.github.io/SG20/PR_0.0.20/html

  2. EPUB format: https://cplusplus.github.io/SG20/PR_0.0.20/guidelines.epub

  3. online (HTML) format, split across multiple HTML documents: https://cplusplus.github.io/SG20/PR_0.0.20/html_split/ [Note: The support for this format needs more work (in order to beautify and fix linking issues).]

Older versions of this document are also available. In general version ver is available at https://cplusplus.github.io/SG20/ver/html. For example, version 0.1.0 (assuming that this version exists) would be available at https://cplusplus.github.io/SG20/0.1.0/html.

2 Context and Aim of This Guide

This document is intended to serve as a resource for instructors to assist in the preparation of courses on C++ in a variety of settings, including university, college, and industry environments. The main objectives of this document are as follows:

  • to provide guidelines for content to be covered by courses of various difficulty levels on C++ (e.g., topics and learning outcomes)
  • to note some common misunderstandings and problematic points that may be encountered when teaching particular topics
  • to suggest resources useful for teaching C++
  • to present examples of curriculum for specific courses

This document does not itself provide a curriculum for a single specific course, but is rather a set of guidelines that can be used to prepare curricula for a wide variety of courses that differ in focus and level of sophistication. (This said, however, some links to other documents with examples of curricula for specific courses may be included herein.) This document only intends to target the teaching of the most recently ratified version of the C++ standard. (This said, however, since older versions of this document are also available, these older versions may be of some use to those who need guidance in older versions of the standard, at least versions that do not predate C++20.)

3 Use of This Document

[NOTE: This document follows the same license model as the C++ Core Guidelines. The LICENSE document is taken verbatim from the C++ Core Guidelines.] This document is made available under a MIT-style license. In simple terms, this license permits copying, use, modification, and creation of derivative works. A copy of the license is included in the section LICENSE.

4 Contributing to This Document

Contributions to this document are welcome. If you would like to help with this project as a contributor, please read the section How to Contribute.

5 Organization of This Document

The various concepts (i.e., ideas) to potentially be covered are partitioned into modules. A module is very broad in scope and consists of numerous topics.

For each module, topics related to the module are identified. Then, for each topic, learning outcomes are specified. In order to address a wide variety of courses on C++, each topic is addressed at three proficiency levels. These proficiency levels allow each topic to be covered at more than one level of detail. This allows target audiences with different background and learning objectives to be accommodated. The three proficiency levels are as follows:

  • foundational: This level gives the learner the idea that a facility exists, what benefits it offers, and the basic ways of using it.

  • main: This level shows mainstream uses and techniques. For abstraction and organizational mechanisms it also demonstrates how to build them. This level should also give the learner a basic (but not detailed) understanding of how a facility might be implemented so that the learner can have a first-order understanding of any costs involved.

  • advanced: This level gives information suitable for an expert. For most topics there is an expert level of knowledge that most programmers rarely need and techniques that require detailed understanding of language rules or library implementation.

The remainder of this document is organized as follows. The various topics are listed grouped by module. In cases where a topic might be classified into more than one module, the topic is listed under the module of most direct relevance. This is done in order to avoid duplication of content. (In the case that a topic is equally relevant to multiple modules, the decision of which to select is made by a proverbial coin toss.) The order in which modules and topics are presented is not meant to imply any order of coverage in a course. The order in which items are listed is essentially arbitrary.

6 Summary of Modules and Topics

In the sections that follow, the various modules and topics are presented. There is one section per module. For each module, a table listing the various topics in that module is provided. The ID for a topic is linked to the detailed coverage of that topic that comes later in the document. If a topic has any learning outcomes at a given proficiency level, this is indicated by a checkmark (“✔️”). If a topic has no learning outcomes (simply because there are not any, not because the information is missing), this is indicated by an em dash (“—”). In the case that the information for a topic is completely missing, a question mark (“?”) symbol is used.

6.1 Compilation Model

ID Unit Foundational Main Advanced
[?] Translation Units ? ? ?
[?] Headers ? ? ?
[?] Modules ? ? ?
[?] Name Mangling ? ? ?
[?] Phases of Translation ? ? ?
[?] Separate Compilation ? ? ?
[?] Linkage ? ? ?

6.2 Preprocessor

ID Unit Foundational Main Advanced
[?] Preprocessor Metaprogramming ? ? ?
[?] Inclusion ? ? ?
[?] Macros ? ? ?

6.3 Basics Types, Objects, Values, Expressions, Statements, and Control-Flow Constructs

ID Unit Foundational Main Advanced
[?] Constant Objects ? ? ?
[?] Declarations ? ? ?
[def] Definitions ✔️ ✔️ ✔️
[?] Selection Constructs (e.g., if, ternary) ? ? ?
[?] Looping Constructs (e.g., for, while, etc.) ? ? ?

6.4 Functions

ID Unit Foundational Main Advanced
[?] Calling Functions ? ? ?
[?] Parameter Passing (e.g., Passing By Value and Reference) ? ? ?
[func-args] Default Arguments ✔️
[?] Returning Multiple Values ? ? ?
[?] Overloading ? ? ?
[udl] User-Defined Literals ✔️ ✔️

6.5 User-Defined Types (Classes)

ID Unit Foundational Main Advanced
[?] Special Member Functions ? ? ?
[?] Types ? ? ?
[?] Conversions ? ? ?
[?] Constructors and Destructors ? ? ?
[?] Move/Copy Constructors and Assignment Operators ? ? ?
[?] Member Functions ? ? ?
[?] Sum Types ? ? ?
[?] User-Defined Literals ? ? ?
[?] Special Member Functions ? ? ?
[?] Guidelines for Special Member Functions (e.g., Rule of Five, Rule of Zero) ? ? ?
[copy] Copy Semantics ✔️ ✔️
[?] Moving and Copying ? ? ?
[?] Lambdas ? ? ?

6.6 Inheritance and Class Hierarchies

ID Unit Foundational Main Advanced
[?] Virtual Functions ? ? ?
[?] Run-Time Type Information ? ? ?

6.7 Compile-Time Computation

ID Unit Foundational Main Advanced
[?] Constant Expressions and Constant Evaluation ? ? ?
[static-assert] static_assert ✔️ ✔️

6.8 Generic Programming (Templates)

ID Unit Foundational Main Advanced
[?] Concepts ? ? ?
[?] SFINAE ? ? ?
[?] Template Metaprogramming ? ? ?
[?] Function Templates ? ? ?
[?] Requires Clauses ? ? ?
[req-expr] Requires Expressions ✔️ ✔️

6.9 Error Handling

ID Unit Foundational Main Advanced
[coe] Categories of Errors ✔️ ✔️
[?] errno ? ? ?
[?] Error Codes ? ? ?
[eh] Exception Handling ✔️ ✔️ ✔️

6.10 Standard Library

ID Unit Foundational Main Advanced
[?] Input/Output (I/O) ? ? ?
[?] Containers, Iterators, and Algorithms ? ? ?

6.11 External (i.e., Non Standard) Libraries

ID Unit Foundational Main Advanced
[?] Graphical User Interfaces ? ? ?

6.12 Building

ID Unit Foundational Main Advanced
[?] Software Build Tools ? ? ?
[?] Strategies for Handling Build Problems ? ? ?

6.13 Testing and Debugging

ID Unit Foundational Main Advanced
[?] Source-Level Debuggers ? ? ?
[?] Code Sanitizers ? ? ?
[?] Test Frameworks ? ? ?
[?] Debugging Strategies ? ? ?

6.14 Tooling

ID Unit Foundational Main Advanced
[?] Compiler Toolchains ? ? ?
[?] IDEs ? ? ?

6.15 Software Design

ID Unit Foundational Main Advanced
[?] Design by Contract ? ? ?

7 Detailed Information for Modules and Topics

7.1 Error handling: Error codes

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

7.1.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objective
Foundational Handling error codes with std::error_code
Main Designing APIs around std::error_code
Advanced

7.1.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

C++ offers a type safe way of passing around errors, contrary to the C-style of error handling, by this, we prevent bugs when passing error codes. Furthermore, error handling with error codes is more commonly used than exception handling, which only should be used in exceptional situations and in some environments is not feasible at all, e.g., in embedded or performance critical software.

7.1.3 Topic introduction

Very brief introduction to the topic.

C++ offers std::error_code, which encapsulates error codes in a type safe way. This topic describes how to use these error codes.

7.1.4 Foundational: Handling error codes with std::error_code

7.1.4.1 Background/Required Knowledge

A student:

7.1.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. write code to handle errors with std::error_code, e.g., obtain the message of the error code or check if an error occurred.
  2. distinguish between the different categories and make justified decisions when to use which

7.1.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

7.1.4.4 Points to cover

This section lists important details for each point.

  • a brief overview of std::error_code and how to use it

7.1.5 Main: Designing APIs around std::error_code

7.1.5.1 Background/Required Knowledge

  • should know how to use reference parameters as an output parameter

7.1.5.2 Student outcomes

A student should be able to:

  1. create an error_code and design API that work with std:error_code
  2. write code that utilizes std::error_category
  3. explain the difference between C-style error handling with errno and std::error_code
  4. make effective use of the interface of std::error_code

7.1.5.3 Caveats

  • reset errno before calling a function that might set errno (better pass an input parameter std::error_code)

7.1.5.4 Points to cover

  • provide a full picture of std::error_code and it’s APIs
  • std::error_category (explorative)

7.1.6 Advanced

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

  • implementing your own error_category

7.1.7 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objective
Foundational Standards exception hierarchy
Main Exception guarantees
Advanced

7.1.8 Motivation

Why is this important? Why do we want to learn/teach this topic?

Exception handling is used to be able to continue the program in case of exceptional situations (like requesting a ridiculous amount of memory: bad_alloc).

7.1.9 Topic introduction

Very brief introduction to the topic.

There are other forms of handling difficult situations, but here we concentrate on exception handling and the peculiarities/characteristics of it. Because there are different forms, we should know when to use which type of handling special situations.

7.1.10 Foundational: Standards exception hierarchy

7.1.10.1 Background/Required Knowledge

A student:

7.1.10.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. Explain how some std:: calls may cause an exception
  2. Discern the different standard exception types
  3. Write simple try … except code (e.g., out of memory, vector at indexing)
  4. Explain on a “simplified” conceptual level what happens when an exception is thrown and is bubbled up through the callers until it is caught

7.1.10.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

  • Exceptions should be used for exceptional situations and should not be used to manage normal control flow.

7.1.10.4 Points to cover

This section lists important details for each point.

  • Exception hierarchy from the standard library
  • Common library functions that may throw exceptions
  • Basic handling exceptions: try/catch/throw
  • How exceptions bubble up until caught

7.1.11 Main: Exception guarantees

7.1.11.1 Background/Required Knowledge

  • RAII
  • Order of construction/destruction of class members

7.1.11.2 Student outcomes

A student should be able to:

  1. Explain the four different exception guarantees
  2. Explain the exception guarantees that the standard library containers offer.
  3. Explain what happens when a exception is thrown in constructor

7.1.11.3 Caveats

  • Make sure code is designed with RAII in mind to prevent resources leaking during exception handling, when the stack is unwound.
  • Care should be taken in constructor design to make all fully constructed members deleted when the stack unwinding mechanism is activated.

7.1.11.4 Points to cover

  • Exception guarantees: Nothrow/Strong/Basic/No
  • Rethrowing an exception

7.1.12 Advanced: Exception-safe containers and edge cases

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

  • Rethrowing a modified exception
  • Writing exception safe containers

7.2 Error handling: Categories of errors

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

7.2.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objective
Foundational Categories of errors
Main Handling different categories of errors
Advanced

7.2.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

Programs can run in a normal state or erroneous state. Students should be able to identify different types of erroneous state and how to best handle them.

7.2.3 Topic introduction

Very brief introduction to the topic.

This topic is an umbrella topic that refers to the different topics for types of errors and error handling.

7.2.4 Foundational: Categories of errors

7.2.4.1 Background/Required Knowledge

A student:

7.2.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. Describe different kinds of errors and exceptional situations that require different approaches of error handling.
  2. Provide some examples of the different error categories.
  3. Identify potential erroneous code sections and attribute them to different error categories.

7.2.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

No caveats at present.

7.2.4.4 Points to cover

This section lists important details for each point.

Errors can happen at different times during software lifetime.

  • Compile-time errors
  • Link-time errors
  • Execution-time errors

There are different types of errors

  • Logic errors (violations of logical preconditions)
  • Run-time errors (errors during code execution due to causes that are external to the program)

7.2.5 Main: Handling different categories of errors

7.2.5.1 Background/Required Knowledge

7.2.5.2 Student outcomes

A student should be able to:

  1. pick the right error handling approach for a given problem.
  2. enumerate different error handling strategies.
  3. make a clear distinction between error-handling code and normal-case handling code

7.2.5.3 Caveats

  • The different error handling strategies have different trade-offs (runtime performance, readability, …)
  • The trade-off space depends on the run-time context (embedded, …)
  • There also exist unhandleable errors (e.g., ODR violations, undefined behavior)

7.2.5.4 Points to cover

7.2.6 Advanced

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

7.3 Functions: user-defined literals

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

7.3.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objectives
Foundational using and understanding UDLs
Main implementing your own UDLs
Advanced Advanced use ("{}, {}!"_fmt("Hello", "World"))

7.3.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

  • Allows clearer expression of intent in C++.
  • std::string: "Hello, world!"s
  • std::chrono: 3h + 10min + 5s

7.3.3 Topic introduction

Very brief introduction to the topic.

  • Explain the existence of user defined literals. Example: 12min + 17s is terse, expressive and type safe.

7.3.4 Foundational: Using UDLs

7.3.4.1 Background/Required Knowledge

A student: * knows how to form numeric literals, e.g., 1.5f means a float of value 1.5. * is familiar with the major C++ types: * bool (Boolean type) * int (Integer type) * double (Floating-point type) * std::string (Text type) * std::vector (Collection type) * knows that namespaces exist, and namespace std. * knows what using-declarations and using-directives are. [C++ object model: declarations]

7.3.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. use using namespace std::string_literals[1].
  2. recognise UDLs in code that they are reading.
  3. figure out which UDL definitions for a used type exist.
  4. identify parts of the standard library that make use of UDLs.
  5. prevent the dangers of temporaries created with "blah"s as well as with std::string{"blah"}.
  6. effectively selects the right set of namespaces in using-directives from the sub-namespaces std::literals.

[1]: explain that it’s okay to use a using-directive to “activate” UDLs.

7.3.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

  • A student gets confused by the similarities and differences between built-in suffixes and UDLs and between UDLs from different namespaces.
  • A student “activates” two suffixes with the same signature from different namespaces.

7.3.4.4 Points to cover

This section lists important details for each point.

7.3.5 Main: implementing UDLs

7.3.5.1 Background/Required Knowledge

  • All of the above.

7.3.5.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. write a UDL operator of their own.
  2. separate unrelated UDLs into distinct namespaces.

7.3.5.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

No caveats at present. #### Points to cover

This section lists important details for each point.

No caveats at present. ### Advanced {#udl-advanced}

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

7.4 Functions: default argument

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

7.4.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Functions in C++ may be overloaded with different numbers and types of parameters. It may be of value to specify default arguments for some number of parameters, to allow a caller to avoid specifying arguments that rarely change, or to enable expanding the set of parameters while maintaining backward compatibility with existing callers.

Level Objective
Foundational Define and use functions with default arguments
Main
Advanced refinement of default arguments through multiple declarations

7.4.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

Default arguments allow the omission of arguments with obvious or common values. Also may be utilized to extend an existing function signature without forcing changes to existing calling code.

7.4.3 Topic introduction

Very brief introduction to the topic.

Explain how default arguments work and how to define them.

7.4.4 Foundational: Using and defining functions with default arguments

7.4.4.1 Background/Required Knowledge

A student is able to:

7.4.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. Call to a function with a default argument with or without that argument specified
  2. Declare a function with a default argument, and omit the default in the definition’s signature
  3. Explain when the lifetime of a default argument begins and ends

7.4.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

  • When no forward-declaration exists, the definition serves as the declaration
  • When multiple declarations exist, only one may specify the default for any particular parameter, but multiple declarations may specify the defaults for different parameters.
  • Additional default values may be specified for other parameters in repeat declarations
  • Calling an overloaded function with fewer arguments may be ambiguous with regard to an overload with default arguments

7.4.4.4 Points to cover

This section lists important details for each point.

  • Default value may only be specified once for each parameter among all declarations
  • Default values must start from the rightmost parameter and continue leftward without gaps
  • Considerations of when to use default arguments vs overload set

7.4.5 Main: implementing *

7.4.5.1 Background/Required knowledge

  • All of the above.

7.4.5.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

7.4.5.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

7.4.5.4 Points to cover

This section lists important details for each point.

7.4.6 Advanced

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

Subsequent redeclarations of the same function may add default argument values, which are then usable by callers. Though a single parameter cannot be given a default argument twice in the same translation unit, it is legal, though ill-advised, to give the same function different default arguments in different translation units.

8 Module name: Passing Parameters by Value

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

8.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objectives
Foundational Defining and calling functions with values
Main
Advanced

8.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

The fundamental element for code-reuse is a function. For functions to be useful, we need to parameterize them. Understanding how to do such is thus fundamental to programming in any language.

8.3 Topic introduction

Very brief introduction to the topic.

Explain how to define functions with parameters and call them with values.

8.4 Foundational: Using reference types to avoid copies

8.4.1 Background/Required Knowledge

A student is able to:

  • Explain what a function is

8.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. Call a function with any number of parameters using the same number of arguments
  2. Define a function with any number of parameters

8.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

8.4.4 Points to cover

This section lists important details for each point.

  • A function is called by invoking the name of the function, followed by parentheses
  • For each parameter in the function signature, a value must be provided, and in the same order
  • Multiple values passed to a function are comma-separated
  • When defining a function, you must list the parameters with the type first, and parameter name second

8.5 Main: Using references to modify external data

8.5.1 Background/Required Knowledge

8.5.2 Student outcomes

8.5.3 Caveats

8.5.4 Points to cover

8.6 Advanced

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

9 Module name: Passing Parameters by Reference

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

9.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objectives
Foundational Avoiding copies using const-reference modifiers
Main Using references to modify external data
Advanced

9.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

9.3 Topic introduction

Very brief introduction to the topic.

Explain what a reference type is and how it constrasts with a value type.

9.4 Foundational: Using reference types to avoid copies

9.4.1 Background/Required Knowledge

A student is able to:

  • Define and call a function with parameters

9.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. Use const-refernce types for function arguments
  2. Explain what considerations to take when deciding whether or not to use a const-reference type

9.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

9.4.4 Points to cover

This section lists important details for each point.

  • No copy of the data is made when taken by constant reference
  • A constant reference value cannot be modified
  • The lifetime of a constant reference cannot be expected to extend beyond the lifetime of the function, so the reference should not be saved off for future use.
  • Taking a reference is not always a time or space savings. Modern machines may use 8-bytes to reference a 4-byte integer, for instance.

9.5 Main: Using references to modify external data

9.5.1 Background/Required Knowledge

  • All of the above

9.5.2 Student outcomes

A student should be able to:

  1. Define and utilize a non-const reference for passing values out of a function

9.5.3 Caveats

9.5.4 Points to cover

  • If the function does not intend to modify the value, const-references should be preferred
  • A reference value may be modified
  • The lifetime of a reference cannot be expected to extend beyond the lifetime of the function, so the reference should not be saved off for future use.
  • Taking a reference is not always a time or space savings. Modern machines may use 8-bytes to reference a 4-byte integer, for instance.

9.6 Advanced

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

9.7 Module name: Requires Expressions

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

9.7.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objectives
Foundational Define and use requires-expressions to check satisfaction of expressions by given parameters
Main Define and use requires-expressions to check properties of expressions
Advanced

9.7.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

Requires-expressions allow a developer to perform compile-time evaluation on the validity of other expressions. These are fundamental to the ability to write concepts. [Compile-time programming: concepts]

9.8 Topic introduction

Very brief introduction to the topic.

Requires-expressions are compile-time predicates which evaluate to true when their specified set of expressions are all valid for a given set of inputs.

9.8.1 Foundational: Writing requires-expressions

9.8.1.1 Background/Required Knowledge

A student is able to:

It is helpful if:

  • The student is aware that attempting to specialize the template with types or values which do not match otherwise unstated assumptions will cause errors within the template.

9.8.1.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. Write a simple-requirement to assert the validity of an expression
  2. Write a type-requirement to check the existence of a type by its identifier
  3. Write a compound-requirement to test the resulting type of an expression
  4. Write a nested-requirement to test the constexpr value of an operation, as opposed to just the syntactic validity
  5. Use a requires-expression within a concept, requires-clause, or if constexpr condition

9.8.1.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

To require that expressions, which evaluate to a boolean value like sizeof(t) == 4, evaluate to true a nested-requirement is needed (e.g., requires sizeof(t) == 4;). Omitting the requires results in a simple-requirement, which is satisfied based purely on syntactic validity, not on the result of the operation.

9.8.1.4 Points to cover

This section lists important details for each point.

  • All requires-expression requirements terminate with a semicolon.
  • simple-requirements are used to check that an expression is well-formed.
  • nested-requirements are introduced with requires and primarily used to check the result of an expression computable by the compiler, including concepts or other requires-expressions.
  • type-requirements are introduced with typename and used to verify the existence of a type with a particular identifier.
  • compound-requirements are enclosed in braces and can be used to check the resulting type of an expression.
  • Checks are performed by the compiler, not at run time.
  • If covering usage of requires-expression with requires-clause, [Compile-time programming: requires clause] demonstrate requires requires and show how to ever avoid writing it by using a concept. [Compile-time programming: concepts]

9.8.2 Main: Advanced requirements

9.8.2.1 Background/Required Knowledge

  • All of the above.
  • Knowledge of noexcept

A student is able to:

9.8.2.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. Write compound-requirements which test the noexceptness of an expression.
  2. Use a concept as the target of a compound-requirement.

9.8.2.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

9.8.2.4 Points to cover

This section lists important details for each point.

  • Compound-requirements allow the optional ability to test whether an expression is marked as noexcept, by using a trailing noexcept keyword.
struct S
{
    void foo() noexcept {}
    void bar() {}
};

static_assert(requires(S s) { { s.foo() } noexcept; } ); // Succeeds. s.foo() is noexcept
static_assert(requires(S s) { { s.bar() } noexcept; } ); // Fails. s.bar() is not noexcept
  • If the return-type-requirement of a compound-requirement is a concept, that concept is given the resulting type as the first parameter, followed by the specified parameters in the compound-requirement. { ++x } -> C<int> would substitute C<decltype((++x)), int> and check that concept C is satisfied for those parameters.

9.8.3 Advanced

See user-defined-literals.

9.9 Meta-error handling: static_assert

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

9.9.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objectives
Foundational Calling static_assert with a constant expression
Main Using static_assert to detect contract violations and improve error messages
Advanced

9.9.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

static_assert allows the developer to enforce that conditions which can be checked during compilation will force build errors when violated. Additionally, they are the best mechanism by which a developer can pass useful information to other developers regarding what violation occurred or what must be done, instead.

9.9.3 Topic introduction

Very brief introduction to the topic.

static_assert is a compile-time evaluated function that asserts the truth of a supplied predicate, issuing an optional user-supplied error message if the predicate is false.

9.9.4 Foundational: Calling static_assert with a constant expression

9.9.4.1 Background/Required Knowledge

A student:

  • Should be able to explain the difference between code evaluated at compile-time and run-time
  • Should be able to cite some examples of compile-time known information, such as sizeof(T)

9.9.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. Assert the expected size of a structure using static_assert

9.9.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

9.9.4.4 Points to cover

This section lists important details for each point.

  • X
  • In addition to what is wrong, a good error message will inform the user of how to correct it

9.9.5 Main: Contracts and static_assert

9.9.5.1 Background/Required Knowledge

  • All of the above.
  • General understanding of compile-time requirements

9.9.5.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. Utilize static_assert to verify preconditions of a meta-function
  2. Utilize static_assert to verify the results of meta-functions for known values

9.9.5.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

9.9.5.4 Points to cover

This section lists important details for each point.

  • When writing a meta-function, use static_assert to test the results
  • Write static_assert calls at the scope of the code they are guarding
template<typename T>
struct container {
    std::map<int, T> vals;

    // Test location #1
    static_assert(
        std::is_default_constructible_v<T>,
        "container type T must be default constructible");i

    void add(int key, T const& t) {
        // Test location #2
        static_assert(
            std::is_default_constructible_v<T>,
            "container type T must be default constructible");
        // std::map::operator[] requires default constructible type for 
        // the value. This will cause a build failure deep in the 
        // implementation of std::map, when T is not default constructible
        vals[key] = t;
    }
};

struct NoDefCtor {
    NoDefCtor() = delete;
    NoDefCtor(double d) {}
};

container<NoDefCtor> c; // If Test #1 was omitted, this would succeed
// This is ill-formed. Test #2 would catch this and provide a better 
// error message for the user
c.add(42, NoDefCtor(1.0)); 

9.9.6 Advanced

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

9.10 C++ object model: Declarations

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

9.10.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objective
Foundational Declaring variables
Main Declaring for programs
Advanced Special cases and peculiarities

9.10.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

  • Introduces a name and it’s type
  • int baz;
  • void bar();
  • class Foo;

9.10.3 Topic introduction

Very brief introduction to the topic.

Introduce names and their associated type in a scope.

9.10.4 Foundational: Declaring variables

9.10.4.1 Background/Required Knowledge

A student:

  • is familiar with the basic C++ types:
    • bool (Boolean type)
    • int (Integer type)
    • double (Floating-point type)

9.10.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. declare a variable with a specific type ‘int baz;’
  2. declare a function ‘void bar();’
  3. declare a class ‘class Foo;’
  4. forward declare a user-defined type or a function
  5. explain the difference between a definition and a declaration

9.10.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

No caveats at present.

9.10.4.4 Points to cover

This section lists important details for each point.

9.10.5 Main: Declarations for programs

9.10.5.1 Background/Required Knowledge

  • All of the above.
  • Basic template syntax

9.10.5.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. create header and source files with a declaration in the former and definition of a variable/function in the latter
  2. declare type aliases to introduce a type with an alternative name ‘using std::string;’
  3. write a forward template declaration

9.10.5.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

  • Declaring aliases can introduce name clashes
  • Prefer using declaration’s over using directives in header files [link]
  • The order of declarations dictates the order of initialization

9.10.5.4 Points to cover

This section lists important details for each point.

9.10.6 Advanced

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

  • asm declaration
  • using-enum-declaration
  • extern “C” declarations

9.11 C++ object model: Definitions

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

9.11.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objective
Foundational Defining variables and ODR
Main Defining for programs
Advanced Special cases and peculiarities

9.11.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

  • A definition is a declaration that supplies all that is needed for a complete entity
  • int baz = 42;
  • void bar() { /* implementation */ }
  • class Foo { /* class body */ };

9.11.3 Topic introduction

Very brief introduction to the topic.

A definition extends a declaration, providing all that is needed for a complete entity, e.g., allocate memory for variables, provide the implementation for functions, complete definitions of data and function members of a class.

9.11.4 Foundational: Defining variables and ODR

9.11.4.1 Background/Required Knowledge

A student:

9.11.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. define a variable with a specific type int baz = 42;
  2. define a function void bar() {}
  3. define a class class Foo {};
  4. explain the one definition rule

9.11.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

No caveats at present.

9.11.4.4 Points to cover

This section lists important details for each point.

  • One definition rule (ODR)

9.11.5 Main: Defining for programs

9.11.5.1 Background/Required Knowledge

9.11.5.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. organize variables, functions, classes into multiple translation units, describing interface with declarations and providing the implementations with definitions without violating ODR.
  2. distinguish between template declaration and definition

9.11.5.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

  • Putting a definition into a header file that is included more than once leads to ODR violations, possibly resulting in linker errors.

9.11.5.4 Points to cover

This section lists important details for each point.

9.11.6 Advanced: Special cases and peculiarities

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

  • ABI Incompatibilities: Different definitions of the same type in multiple object files can lead to subtle program errors.

9.12 C++ object model: copy semantics

Skeleton descriptions are typeset in italic text, so please don’t remove these descriptions when editing the topic.

9.12.1 Overview

Provides a short natural language abstract of the module’s contents. Specifies the different levels of teaching.

Level Objectives
Foundational understanding how and when are copies made
Main implementing user-defined copy operations
Advanced special cases: copy elision

9.12.2 Motivation

Why is this important? Why do we want to learn/teach this topic?

Copy semantics allows the user to define how objects of a class get replicated and interact on a value level.

9.12.3 Topic introduction

Very brief introduction to the topic.

Explains when and how objects are copied.

9.12.4 Foundational: How and when are copies made

9.12.4.1 Background/Required Knowledge

A student is able to: * explain what a C++ type is? [C++ object model: types] * explain what an object is? [C++ object model: objects], [C++ object model: constant objects] * define and understand class invariants?

It helps when a student is able to: * use move semantics [C++ object model: move semantics] * explain special member functions [C++ object model: special member functions]

9.12.4.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to:

  1. explain what copy semantics accomplish
  • establishing “equivalent” object state in another object
  1. explain difference between copying a reference and copying a value*
  2. explain where copies are made

* In other languages these differences are sometimes referred to as shallow and deep copy.

9.12.4.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

  • Compiler-provided copy operations may result in ownership problems (e.g., char*). These ownership problems can generally be solved by using types whose copy operations have the appropriate semantics, e.g., std::string instead of char* to hold string values.

9.12.4.4 Points to cover

This section lists important details for each point.

  • Principle of copying
    • Copying of types, which follow the rule of zero
    • Copying of types, with user defined copy operations
    • Copying an object does not change the original
  • Practical applications
    • std::unique_ptr (has no copy)
    • Strings (copies the value)

9.12.5 Main: Implementing user-defined copy operations

9.12.5.1 Background/Required Knowledge

A student is able to: * identify special member functions [C++ object model: special member functions]

It helps when a student is able to: * use move semantics [C++ object model: move semantics] * explain the rule of zero [C++ object model: rule-of-zero] * explain the rule of five [C++ object model: rule-of-five]

9.12.5.2 Student outcomes

A list of things “a student should be able to” after the curriculum. The next word should be an action word and testable in an exam. Max 5 items.

A student should be able to: * explain when they have to implement the copy operations for their own type * Copy constructor * Copy assignment operator * implement copy operations for their own types * Optional: explain when copying with basic and strong exception guarantees is useful

9.12.5.3 Caveats

This section mentions subtle points to understand, like anything resulting in implementation-defined, unspecified, or undefined behavior.

  • Intricacies when implementing copy operations:
    • Examples of how not to write copy operations (e.g., C++03 std::auto_ptr)

9.12.5.4 Points to cover

This section lists important details for each point.

  • Copy constructors and copy assignment operators
    • How compiler generates default copy operations
    • =default, =delete (No copy)
    • How-to write your own copy operations
    • Rule-of-five
    • Copy assignment operators can be ref-qualified to avoid assigning into temporary objects.

9.12.6 Advanced

These are important topics that are not expected to be covered but provide guidance where one can continue to investigate this topic in more depth.

When can copies be elided and when does the standard guarantee copy elision. References: * Abseil tip of the Week #166 * cppreference - Copy elision

See concepts.

10 License

[NOTE: This license is copied verbatim from the C++ Core Guidelines.]

Copyright (c) Standard C++ Foundation and its contributors

Standard C++ Foundation grants you a worldwide, nonexclusive, royalty-free,
perpetual license to copy, use, modify, and create derivative works from this
project for your personal or internal business use only. The above copyright
notice and this permission notice shall be included in all copies or
substantial portions of the project. This license does not grant permission
to use the trade names, trademarks, service marks, or product names of the
licensor, except as required for reasonable and customary use in describing
the origin of the project.

Standard C++ Foundation reserves the right to accept contributions to the
project at its discretion.

By contributing material to this project, you grant Standard C++ Foundation,
and those who receive the material directly or indirectly from Standard C++
Foundation, a perpetual, worldwide, non-exclusive, royalty-free, irrevocable,
transferrable license to reproduce, prepare derivative works of, publicly
display, publicly perform, and distribute your contributed material and such
derivative works, and to sublicense any or all of the foregoing rights to third
parties for commercial or non-commercial use.  You also grant Standard C++
Foundation, and those who receive the material directly or indirectly from
Standard C++ Foundation, a perpetual, worldwide, non-exclusive, royalty-free,
irrevocable license under your patent claims that directly read on your
contributed material to make, have made, use, offer to sell, sell and import
or otherwise dispose of the material. You warrant that your material is your
original work, or that you have the right to grant the above licenses.

THE PROJECT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE PROJECT OR THE USE OR OTHER DEALINGS IN THE
PROJECT.

If you believe that anything in the project infringes your copyright, please
contact us at admin@isocpp.org with your contact information and a detailed
description of your intellectual property, including a specific URL where you
believe your intellectual property is being infringed.

11 Contributors

Christopher Di Bella
Florian Sattler
Michael Adams
rwdougla

12 How To Contribute

Before attempting to contribute any content for consideration for inclusion in this document, please read the information below and and the referenced documents as appropriate.

All contributions to this project must be made in accordance with the license in section License. This teaching-guidelines document only offers guidance on teaching C++ as it is specified in the current version of the C++ standard. So, content should be presented relative to the most-recently ratified version of the standard. A detailed explanation of how to present the material for a topic is given in:

  • JC van Winkel, Bjarne Stroustrup, and Florian Sattler. P2193 — How to structure a teaching topic. https://wg21.link/p2193.

Any potential contributors should ensure that they read this document. The following document may also be helpful in providing some general background on the modular approach to teaching followed herein:

In order to prepare content, it is important to understand what learning outcomes are, and how to prepare good ones. Some information on learning outcomes can be found in the References section. The following document offers a concise introduction to learning outcomes:

13 Glossary

Some possible terms to include in the glossary:

  • learning objective
  • learning outcome

14 References

14.1 References on Learning Outcomes

  • Christopher Di Bella, Simon Brand, and Michael Adams. P1389R0 — Standing Document for SG20: Guidelines for Teaching C++ to Beginners. https://wg21.link/p1389.

  • Christopher Di Bella. P1725R0 — Modular Topic Design. https://wg21.link/p1725.

  • JC van Winkel, Bjarne Stroustrup, and Florian Sattler. P2193 — How to structure a teaching topic. https://wg21.link/p2193.

  • JC van Winkel and Christopher Di Bella. P1231 — Proposal for Study Group: C++ Education. https://wg21.link/p1231.

  • H. Hinnant, R. Orr, B. Stroustrup, D. Vandevoorde, and M. Wong. P2000 — Direction for ISO C++, Section 5.1. https://wg21.link/p2000r0.