Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions CppCoreGuidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -17074,7 +17074,7 @@ Template interface rule summary:
* [T.42: Use template aliases to simplify notation and hide implementation details](#rt-alias)
* [T.43: Prefer `using` over `typedef` for defining aliases](#rt-using)
* [T.44: Use function templates to deduce class template argument types (where feasible)](#rt-deduce)
* [T.46: Require template arguments to be at least semiregular](#rt-regular)
* [T.46: Prefer template arguments to be movable and default-constructible](#rt-regular)
* [T.47: Avoid highly visible unconstrained templates with common names](#rt-visible)
* [T.48: If your compiler does not support concepts, fake them with `enable_if`](#rt-concept-def)
* [T.49: Where possible, avoid type-erasure](#rt-erasure)
Expand Down Expand Up @@ -18110,7 +18110,7 @@ For example:

Flag uses where an explicitly specialized type exactly matches the types of the arguments used.

### <a name="rt-regular"></a>T.46: Require template arguments to be at least semiregular
### <a name="rt-regular"></a>T.46: Prefer template arguments to be movable and default-constructible

##### Reason

Expand All @@ -18120,6 +18120,7 @@ Most uses support that anyway.

##### Example

// X is not default constructible
class X {
public:
explicit X(int);
Expand All @@ -18135,13 +18136,13 @@ Most uses support that anyway.
X y = x; // fine
std::vector<X> v(10); // error: no default constructor

##### Note
##### Exceptions

Semiregular requires default constructible.
A trait type is not necessarily movable and default-constructible. Templates that use trait types usually use them with `Trait::something` scope resolution syntax, rather than using objects of the trait type.
Copy link
Contributor

@jwakely jwakely Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A trait type is not necessarily movable and default-constructible.

I don't think this is true, all standard trait types are movable and default constructible, and you probably want them to be so that you can use them for tag dispatching.

Templates that use trait types usually use them with Trait::something scope resolution syntax, rather than using objects of the trait type.

OK, this is true, but irrelevant.

I don't think the issue is saying that trait types themselves are not movable and therefore we need an exception for trait types. I think it's saying that using non-movable types as the template arguments of traits violates the guideline. But of course we want to be able to use std::is_move_assignable_v<X> and is_default_constructible_v<X> even if X is not movable or not default constructible.

So I think this change misses the mark.

I think if you want to keep the rule then you should do something like make an exception for templates which do not actually construct the type, e.g. type traits which are purely compile-time queries for properties of a type and do not have any side effects.

The case of unique_ptr<X> requires a different exception. That certainly does do things with an object of type X but there is no reason whatsoever that it needs X to be semiregular. It never makes a new object of type X, and using unique_ptr to manage non-movable objects on the heap is a perfectly valid thing to do.


##### Enforcement

* Flag types used as template arguments that are not at least semiregular.
* Flag types used as template arguments that do not satisfy both `std::movable` and `std::default_constructible` and that are using in the template without `::` scope resolution syntax.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be "that are used" not "that are using", but I think the change just needs to be rewritten anyway.


### <a name="rt-visible"></a>T.47: Avoid highly visible unconstrained templates with common names

Expand Down