Movatterモバイル変換


[0]ホーム

URL:



This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofC++23 status.

3655. TheINVOKE operation andunion types

Section: 22.10.4[func.require]Status:C++23Submitter: Jiang AnOpened: 2021-12-29Last modified: 2023-11-22

Priority:3

View otheractive issues in [func.require].

View all otherissues in [func.require].

View all issues withC++23 status.

Discussion:

There are two cases of theINVOKE operation specified withstd::is_base_of_v (22.10.4[func.require] (1.1), (1,4)), which means the following code snippet is ill-formed, asstd::is_base_of_v<B, D> isfalse when eitherB orD is aunion type.

union Foo { int x; };static_assert(std::is_invocable_v<int Foo::*, Foo&>);

Currently libstdc++ accepts this code, because it uses slightly different conditions that handleunion types. libc++ and MSVC STL reject this code as specified in 22.10.4[func.require].

Should we change the conditions in 22.10.4[func.require] (1.1) and (1.4) to match libstdc++ and correctly handleunion types?

[2022-01-30; Reflector poll]

Set priority to 3 after reflector poll.

[2023-02-07; Jonathan adds wording]

This is a regression introduced by LWG2219(i).In C++14std::result_of<int Foo::*(Foo&)>::typewas valid, because theINVOKE wording used to say"f is a pointer to member data of a classTandt1 is an object of typeTor a reference to an object of typeTor a reference to an object of a type derived fromT".Since LWG 2219 we useis_base_of which is always false forunion types.I don't think LWG 2219 intended to break this case, so we should fix it.

Previous resolution [SUPERSEDED]:

This wording is relative toN4928.

  1. Modify 22.10.4[func.require] as indicated:

    -1-DefineINVOKE(f, t1, t2, …, tN) as follows:

    • (1.1) —(t1.*f)(t2, …, tN)whenf is a pointer to a member function of a classT andis_same_v<T, remove_cvref_t<decltype(t1)>> ||is_base_of_v<T, remove_reference_t<decltype(t1)>>istrue;
    • (1.2) —(t1.get().*f)(t2, …, tN)whenf is a pointer to a member function of a classT andremove_cvref_t<decltype(t1)>is a specialization ofreference_wrapper;
    • (1.3) —((*t1).*f)(t2, …, tN)whenf is a pointer to a member function of a classT andt1 does not satisfy the previous two items;
    • (1.4) —t1.*fwhenN == 1 andf is a pointer to data member of a classT andis_same_v<T, remove_cvref_t<decltype(t1)>> ||is_base_of_v<T, remove_reference_t<decltype(t1)>>istrue;
    • (1.5) —t1.get().*fwhenN == 1 andf is a pointer to data member of a classT andremove_cvref_t<decltype(t1)>is a specialization ofreference_wrapper;
    • (1.6) —(*t1).*fwhenN == 1 andf is a pointer to data member of a classT andt1 does not satisfy the previous two items;
    • (1.7) —f(t1, t2, …, tN) in all other cases.

[2023-02-07; Jonathan provides wording change requested by LWG]

Changeremove_reference_t toremove_cvref_t.is_base_of ignores cv-qualifiers, so this isn't necessary,but just using the same transformation in both cases seems simpler to grok.

[Issaquah 2023-02-07; LWG]

Move to Immediate for C++23

[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Immediate → WP.]

Proposed resolution:

This wording is relative toN4928.

  1. Modify 22.10.4[func.require] as indicated:

    -1-DefineINVOKE(f, t1, t2, …, tN) as follows:

    • (1.1) —(t1.*f)(t2, …, tN)whenf is a pointer to a member function of a classT andis_same_v<T, remove_cvref_t<decltype(t1)>> ||is_base_of_v<T, remove_referencecvref_t<decltype(t1)>>istrue;
    • (1.2) —(t1.get().*f)(t2, …, tN)whenf is a pointer to a member function of a classT andremove_cvref_t<decltype(t1)>is a specialization ofreference_wrapper;
    • (1.3) —((*t1).*f)(t2, …, tN)whenf is a pointer to a member function of a classT andt1 does not satisfy the previous two items;
    • (1.4) —t1.*fwhenN == 1 andf is a pointer to data member of a classT andis_same_v<T, remove_cvref_t<decltype(t1)>> ||is_base_of_v<T, remove_referencecvref_t<decltype(t1)>>istrue;
    • (1.5) —t1.get().*fwhenN == 1 andf is a pointer to data member of a classT andremove_cvref_t<decltype(t1)>is a specialization ofreference_wrapper;
    • (1.6) —(*t1).*fwhenN == 1 andf is a pointer to data member of a classT andt1 does not satisfy the previous two items;
    • (1.7) —f(t1, t2, …, tN) in all other cases.

[8]ページ先頭

©2009-2026 Movatter.jp