This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

### 3046. Do not require `reference_wrapper` to support non-referenceable function types

Section: 20.14.6 [refwrap] Status: New Submitter: Jonathan Wakely Opened: 2017-12-14 Last modified: 2020-09-06

Priority: 3

View all other issues in [refwrap].

View all issues with New status.

Discussion:

[refwrap] says that `reference_wrapper<T>` is a "wrapper around a reference to an object or function of type `T`" but this doesn't actually constrain it, and doesn't forbid non-referenceable function types like `int() const`.

There is no way to construct a `reference_wrapper<int() const>` but implementations are required to provide partial specializations for functions with cv-qualifiers and ref-qualifiers in order to define a nested `result_type`. It should be undefined to instantiate `reference_wrapper<T>` with a non-referenceable type, or with a reference type (since references to references are not possible). Making it undefined (rather than ill-formed or unspecified) means implementations are not required to diagnose such invalid specializations, but also don't have to go to the effort of supporting weak result types etc.

[2018-01; Priority set to 3 after mailing list discussion]

Previous resolution [SUPERSEDED]:

> This wording is relative to N4713.

> 1. Modify 20.14.6 [refwrap] as indicated:

>    > -1- `reference_wrapper<T>` is a `CopyConstructible` and `CopyAssignable` wrapper around a reference to an object or function of type `T`. `T` shall be a referenceable type (3.45 [defns.referenceable]) that is not a reference type.

>    > -2- `reference_wrapper<T>` shall be a trivially copyable type (6.8 [basic.types]).

[2019-03-15; Daniel comments and provides revised wording]

The current wording is now far behind the working draft and a synchronization is therefore recommended. In particular, with the acceptance of P0357R1, the specification of `reference_wrapper` has no longer any weak result type. Second, I would like to concur with a remark from Tomasz to change the wording to replace the undefined behavior by an ill-formed program instead, because every attempt to instantiate the definition of `reference_wrapper` will instantiate its member declarations, and this would cause the program to become ill-formed anyway because of the illegal formation of references to non-referenceable function types for member functions such as `T& get() const noexcept`.

As concrete wording suggestion I would recommend wording that ensures that an ill-formed program is only required when a specialization of `reference_wrapper` is instantiated, because in the absence of a constrained template parameter we shouldn't require implementations to diagnose even forming the name of a `reference_wrapper` specialization such as in the following example:

>     using X = reference_wrapper<int() const>;

The wording below does not take advantage of a Mandates: element to prevent a dependency on LWG 3193 and because such an element is rarely used to specify class templates. If the committee wishes to use such an element, the equivalent wording would be:

> Mandates: `reference_wrapper` is instantiated with a referenceable type (3.45 [defns.referenceable]) as the argument for the template parameter `T`.

Proposed resolution:

This wording is relative to N4800.

1. Modify 20.14.6 [refwrap] as indicated:

   > -1- `reference_wrapper<T>` is a Cpp17CopyConstructible and Cpp17CopyAssignable wrapper around a reference to an object or function of type `T`. If `reference_wrapper` is instantiated with a non-referenceable type (3.45 [defns.referenceable]) as the argument for the template parameter `T`, the program is ill-formed.

   > -2- `reference_wrapper<T>` is a trivially copyable type (6.8 [basic.types]).

   > -3- The template parameter `T` of `reference_wrapper` may be an incomplete type.