Toronto adopts concepts into the next C++ working draft
Concepts enter draft C++20 with changes to definition syntax and limits on shorthand forms. The merge separates established constraint machinery from notation that still lacks consensus.
A template interface can state requirements before its implementation tries to use an unsuitable argument. That is the practical purpose of concepts, and Toronto moves the facility from a separate technical specification into the next C++ working draft. The committee adopts most of the Concepts TS while leaving some shorthand syntax out. This is a concrete decision about which parts of the design are ready to become the language's common model.
Herb Sutter's July 15 meeting report calls concepts the first major language feature voted into draft C++20. He also states that nothing at this meeting changes C++17, whose technical work is already complete. The adoption belongs to the next revision cycle, so using C++17 mode does not by itself promise this new draft facility.
The 2015 Concepts TS draft provides the technical background for the merge. It describes constraints, requires-expressions and their role in selecting templates. Toronto's changes should be read against that established machinery, with the meeting report identifying the specific syntax decisions made during adoption.
I value this direction because templates' runtime efficiency has often come with difficult diagnostics. A declared requirement gives a failed call a more useful explanation than whatever operation first fails inside a long instantiation chain. The benefit depends on preserving a precise account of what the constraint checks, rather than treating a concept name as a general proof of correct behavior.
Constraints become part of the declared interface
A concept is a named compile-time predicate on template arguments. Its definition can ask whether certain expressions are valid, whether associated types exist or whether other constraints hold. A template can then use that predicate in a requires clause to restrict the arguments for which it participates.
The TS's requires-expression is unevaluated. Parameters introduced for stating its requirements have no runtime storage or lifetime. They provide notation for the compiler to examine operations, so asking whether two values can be added does not create those values and execute an addition as a test.
This is the source of the runtime cost argument. Constraints help determine whether a template applies during translation. They do not require a runtime object describing every permissible type or a virtual call for each constrained operation. The selected specialization still contains the ordinary operations written in its implementation.
Requirements can also describe relationships among several types. An algorithm searching a sequence needs a comparison between an element and a sought value, which need not have identical types. Naming only a property of each type independently can miss that relationship. Multi-argument predicates give the interface a place to state it directly.
That expressiveness matters for independently developed components. A type can satisfy an algorithm's requirements through the operations it already provides. The mechanism does not require editing the type to inherit a common base or explicitly register every matching concept. The compiler checks the relevant properties when it needs to determine satisfaction.
Toronto simplifies concept definitions
Sutter reports two changes to the definition forms. The adopted design removes the need to write bool after concept, and it removes function concepts until there is a demonstrated need for overloading concepts. A reader of TS-era examples therefore needs to distinguish their syntax from the form entering the new working draft.
For a simple predicate, the resulting definition can be written as follows. This illustrates the Toronto direction and is not a claim of support in every released compiler.
template<class T>
concept SmallObject = sizeof(T) <= 16;
template<class T>
requires SmallObject<T>
void inspect_small(const T&);
The predicate's expression produces the Boolean requirement without a separate function call. Removing function concepts also removes the need to remember whether a particular concept name requires empty parentheses in an explicit constraint. This is a use-site simplification as well as a definition change.
Eric Niebler's June Ranges proposal documents the corresponding library tension. Function concepts allowed related predicates of different arities to share a name. Switching to variable concepts required separate names for cross-type relationships and more explicit names for indirect unary callable requirements.
That history explains the qualification in Sutter's report about revisiting function concepts if a need appears. The adopted subset chooses simpler definitions now without claiming that naming every relationship has become trivial. A library still needs to design useful predicates and make their parameter relationships clear.
Some shorthand remains outside the merge
The meeting report explicitly excludes introducer syntax and terse or natural syntax from the initial adoption. Sutter says unresolved design issues remain and that the evolution group intends to pursue the shorter notation. The report therefore does not justify presenting every compact declaration from an earlier concepts tutorial as adopted C++20 draft syntax.
This is a useful separation of mechanism and notation. A named requirement with an explicit requires clause can express a constraint even while the committee continues discussing a shorter spelling. The uncertainty over shorthand does not mean the whole constraint system remains outside the working draft.
Conversely, merging the established mechanism does not settle every syntactic proposal around it. A standards account should name the excluded pieces instead of reducing the event to an unqualified statement that the entire TS was copied unchanged. Implementers and library authors need to know which version of the design their examples target.
Constraint ordering has defined limits
The TS describes subsumption, the relation used to compare constraints. A stronger requirement can help distinguish between otherwise viable candidates. That lets an algorithm provide an implementation for a broad set of arguments and another for arguments satisfying additional requirements.
The document also warns against assuming a general theorem prover. Its example says subsumption does not determine the implication between arbitrary numerical predicates such as nonnegative and positive bounds. The formal ordering operates through the specified structure and equivalence of constraints, not every mathematical fact a reader might infer from their source text.
Library definitions consequently matter to overload behavior. Reusing a named requirement in a refinement gives the compiler a specified relationship to examine. Merely writing two expressions that a human regards as related is not a substitute for understanding how the constraint system compares them.
There is a second limit on the apparent promise of a name. A valid expression requirement can show that an operation exists and that its result has an appropriate type. It cannot by itself establish every semantic law the algorithm expects. A comparison operation's syntax does not prove its ordering behavior for all values.
This leaves documentation and testing with a concrete role. Constraints can reject types lacking the stated operations before an algorithm instantiates unsuitable implementation code. The semantic requirements still explain what those operations must mean for the algorithm's result to be correct. The adoption improves the interface without abolishing the need for that explanation.
The TS also separates forming a class specialization from checking each member's associated constraints. Its example gives a class template differently constrained constructors. The constructors remain members even when their constraints prevent selection for a particular argument. This allows an interface to describe alternative operations without requiring every alternative to be usable for every specialization. It is another reason to treat constraints as part of candidate selection and interface availability. They are not an instruction to execute all alternative implementations and discover which one works after entering the function.
Separate specifications continue on their own schedules
Toronto also completes the Coroutines, Networking and Ranges technical specifications for publication, according to Sutter. Modules proceeds to its comment ballot. These are distinct statuses, and none should be silently added to the list of facilities adopted into the C++20 working draft merely because their work happened at the same meeting.
The concepts merge has a particular consequence for library development. Sutter reports that the library evolution group expects to begin integrating concepts in its next meeting. A language mechanism adopted early in a revision cycle gives that work a basis, while the exact library requirements still need their own design and review.
I favor the merge's explicit boundary. The working draft gains named constraints and the machinery needed to select suitable templates, while definition syntax becomes simpler and disputed shorthand remains separate. That gives generic libraries a concrete interface model to use. It also makes it possible to explain the remaining work precisely, including semantic requirements that the compiler cannot prove and notation that the committee has not yet adopted.