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

`ConvertibleTo`

prose does not match code**Section:** 18.4.4 [concept.convertible] **Status:** C++20
**Submitter:** Hubert Tong **Opened:** 2019-03-05 **Last modified:** 2021-02-25

**Priority: **1

**View other** active issues in [concept.convertible].

**View all other** issues in [concept.convertible].

**View all issues with** C++20 status.

**Discussion:**

The prose in N4800 subclause [concept.convertibleto] indicates that the requirement is for an expression of a particular type and value category to be both implicitly and explicitly convertible to some other type. However, for a type

struct A { A(const A&) = delete; };

`ConvertibleTo<const A, A>`

would be `false`

despite the following being okay:

const A f(); A test() { static_cast<A>(f()); return f(); }

*[2019-03-15 Priority set to 1 after reflector discussion]*

*[2019-07-14 Tim adds PR based on discussion in 2019-07-09 LWG telecon]*

This wording is relative to N4820, and also resolves LWG 3151.

Modify [concept.convertibleto] as indicated:

-1- The

`ConvertibleTo`

concept requires~~an~~a glvalue expression of a particular type and value category to be both implicitly and explicitly convertible to some other type. The implicit and explicit conversions are required to produce equal results.template<class From, class To> concept ConvertibleTo = is_convertible_v<From, To> && requires(add_rvalue_reference_t<From> (&f)()) { static_cast<To>(f()); };-2- Let

`test`

be the invented function:To test(add_rvalue_reference_t<From> (&f)()) { return f(); }for some types

`From`

and`To`

, and let`f`

be a function with no arguments and return type`add_rvalue_reference_t<From>`

such that`f()`

is equality-preserving.`From`

and`To`

model`ConvertibleTo<From, To>`

only if:

(2.1) —

`To`

is not an object or reference-to-object type, or`static_cast<To>(f())`

is equal to`test(f)`

.(2.2) —

`add_rvalue_reference_t<From>`

is not a reference-to-object type, or

(2.2.1) — If

`add_rvalue_reference_t<From>`

is an rvalue reference to a non const-qualified type, the resulting state of the object referenced by`f()`

after either above expression is valid but unspecified (16.4.6.15 [lib.types.movedfrom]).(2.2.2) — Otherwise, the object referred to by

`f()`

is not modified by either above expression.

*[2019-09-23; Daniel adjusts wording to working draft changes]*

Due to the concept renaming caused by P1754R1 the proposed wording is outdated and needs adjustments.

This wording is relative to N4830, and also resolves LWG 3151.

Modify 18.4.4 [concept.convertible] as indicated:

-1- The

`convertible_to`

concept requires~~an~~a glvalue expression of a particular type and value category to be both implicitly and explicitly convertible to some other type. The implicit and explicit conversions are required to produce equal results.template<class From, class To> concept convertible_to = is_convertible_v<From, To> && requires(add_rvalue_reference_t<From> (&f)()) { static_cast<To>(f()); };-2- Let

`test`

be the invented function:To test(add_rvalue_reference_t<From> (&f)()) { return f(); }for some types

`From`

and`To`

, and let`f`

be a function with no arguments and return type`add_rvalue_reference_t<From>`

such that`f()`

is equality-preserving.`From`

and`To`

model`convertible_to<From, To>`

only if:

(2.1) —

`To`

is not an object or reference-to-object type, or`static_cast<To>(f())`

is equal to`test(f)`

.(2.2) —

`add_rvalue_reference_t<From>`

is not a reference-to-object type, or

(2.2.1) — If

`add_rvalue_reference_t<From>`

is an rvalue reference to a non const-qualified type, the resulting state of the object referenced by`f()`

after either above expression is valid but unspecified (16.4.6.15 [lib.types.movedfrom]).(2.2.2) — Otherwise, the object referred to by

`f()`

is not modified by either above expression.

*[2019-11-06 Tim updates PR based on discussion in Belfast LWG evening session]*

"glvalue" is incorrect because we want to allow testing `convertible_to<void, void>`

. It's also less than clear
how the "expression" and "a particular type" in the first sentence correspond to the parameters of the concept.

This wording is relative to N4835, and also resolves LWG 3151.

Modify 18.4.4 [concept.convertible] as indicated:

-1- The

`convertible_to`

concept for types`From`

and`To`

requires an expression`E`

such that`decltype((E))`

is`add_rvalue_reference_t<From>`

~~of a particular type and value category~~to be both implicitly and explicitly convertible to~~some other type~~`To`

. The implicit and explicit conversions are required to produce equal results.template<class From, class To> concept convertible_to = is_convertible_v<From, To> && requires(add_rvalue_reference_t<From> (&f)()) { static_cast<To>(f()); };-2- Let

`FromR`

be`add_rvalue_reference_t<From>`

and`test`

be the invented function:To test(FromR (&f)()) { return f(); }for some types

`From`

and`To`

, and let`f`

be a function with no arguments and return type`FromR`

such that`f()`

is equality-preserving.`From`

and`To`

model`convertible_to<From, To>`

only if:

(2.1) —

`To`

is not an object or reference-to-object type, or`static_cast<To>(f())`

is equal to`test(f)`

.(2.2) —

`FromR`

is not a reference-to-object type, or

(2.2.1) — If

`FromR`

is an rvalue reference to a non const-qualified type, the resulting state of the object referenced by`f()`

after either above expression is valid but unspecified (16.4.6.15 [lib.types.movedfrom]).(2.2.2) — Otherwise, the object referred to by

`f()`

is not modified by either above expression.

*[2019-11-09 Tim rephrased first sentence based on discussion in Belfast LWG Saturday session]*

*[Status to Tentatively ready after Belfast LWG Saturday session]*

**Proposed resolution:**

This wording is relative to N4835, and also resolves LWG 3151.

Modify 18.4.4 [concept.convertible] as indicated:

-1- Given types

`From`

and`To`

and an expression`E`

such that`decltype((E))`

is`add_rvalue_reference_t<From>`

,`convertible_to<From, To>`

~~The~~requires`convertible_to`

concept`E`

~~an expression of a particular type and value category~~to be both implicitly and explicitly convertible to~~some other~~type`To`

. The implicit and explicit conversions are required to produce equal results.template<class From, class To> concept convertible_to = is_convertible_v<From, To> && requires(add_rvalue_reference_t<From> (&f)()) { static_cast<To>(f()); };

-2- Let

`FromR`

be`add_rvalue_reference_t<From>`

and`test`

be the invented function:To test(FromR (&f)()) { return f(); }

for some types

`From`

and`To`

, and let`f`

be a function with no arguments and return type`FromR`

such that`f()`

is equality-preserving.`From`

and`To`

model`convertible_to<From, To>`

only if:`To`

is not an object or reference-to-object type, or`static_cast<To>(f())`

is equal to`test(f)`

.(2.2) —

`FromR`

is not a reference-to-object type, or(2.2.1) — If

`FromR`

is an rvalue reference to a non const-qualified type, the resulting state of the object referenced by`f()`

after either above expression is valid but unspecified (16.4.6.15 [lib.types.movedfrom]).(2.2.2) — Otherwise, the object referred to by

`f()`

is not modified by either above expression.