This is an archive of the discontinued LLVM Phabricator instance.

[libc++] reference_wrapper does not define nested types as described in C++11/14
Needs ReviewPublic

Authored by xingxue on Jul 6 2022, 2:39 PM.

Details

Reviewers
ldionne
philnik
Mordante
hubert.reinterpretcast
daltenty
EricWF
Group Reviewers
Restricted Project
Summary

This patch tries to fix the issue that the implementation of reference_wrapper does not define nested types as described in C++11/14 standard section 20.8.3/20.9.3 [refwrap]. When T is a class with a nested type argument_type T1, the template instantiation reference_wrapper<T> shall define a nested type named argument_type as a synonym for T1. When T is a class with nested types named first_argument_type and second_argument_type of type T1 and T2, the template instantiation reference_wrapper<T> shall define two nested types named first_argument_type and second_argument_type as synonyms for T1 and T2, respectively. These types are deprecated in C++17 and removed in C++20.

The following test case demonstrates the issue.

#include <functional>

int main(void) {
  struct S{
    typedef int argument_type;
    typedef long first_argument_type;
    typedef float second_argument_type;
  };
  typedef std::reference_wrapper<S>::argument_type A1;
  typedef std::reference_wrapper<S>::first_argument_type A2;
  typedef std::reference_wrapper<S>::second_argument_type A3;
  static_assert(std::is_same<S::argument_type, A1>::value, "");
  static_assert(std::is_same<S::first_argument_type, A2>::value, "");
  static_assert(std::is_same<S::second_argument_type, A3>::value, "");
  return 0;
}

Diff Detail

Event Timeline

xingxue created this revision.Jul 6 2022, 2:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 6 2022, 2:39 PM
xingxue requested review of this revision.Jul 6 2022, 2:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 6 2022, 2:39 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript

Friendly ping.

Gentle ping.

Gentle ping.

Gentle ping.

EricWF added a subscriber: EricWF.Sep 14 2023, 2:23 PM

@xingxue I apologize on behalf of the project for dropping this? Are you still willing to land it. If so, we can have it reviewed and completed this week.

xingxue added a comment.EditedSep 15 2023, 6:28 AM

@xingxue I apologize on behalf of the project for dropping this? Are you still willing to land it. If so, we can have it reviewed and completed this week.

Thanks very much @EricWF! Yeah, it will be appreciated if we could have it reviewed and completed at your convenience! This affects some test cases in Perennial.

xingxue edited reviewers, added: EricWF; removed: cebowleratibm.Sep 16 2023, 4:48 AM
ldionne requested changes to this revision.Oct 10 2023, 9:57 PM
ldionne added inline comments.
libcxx/include/__functional/weak_result_type.h
67–68

You should use __void_t instead, it is available in all Standard modes.

70
101

Plugging this here means that we also change the behavior of things like std::mem_fn. It looks like that's a good change, however we should also test it. Can you please make the fix not only for std::reference_wrapper but also for the other things like std::mem_fn that seem to be mis-behaving right now?

libcxx/test/libcxx/utilities/function.objects/refwrap/refwrap_types.pass.cpp
1

I would name this test libcxx/test/libcxx/utilities/function.objects/refwrap/argument_types.compile.pass.cpp or something like that. But at least let's make it a .compile.pass.cpp test since it is compile-only.

24

You should make this function just be void test() instead of main after moving it to .compile.pass.cpp. Those tests are never run, only compiled, and not having a main() function in a compile-only test helps avoid confusion about whether the test is run.

27

We should add a test that reference_wrapper<T> has no such nested types if T isn't a function type or a type with these types nested.

In other words, we want to positively assert that reference_wrapper<int> (for example) doesn't provide a meaningless argument_type typedef (and same for the other ones).

libcxx/test/std/depr/depr.function.objects/depr.base/refwrap_types.depr.verify.cpp
9–13

Let's move the REQUIRES above // <functional> to avoid breaking up the synopsis like that.

This revision now requires changes to proceed.Oct 10 2023, 9:57 PM
xingxue updated this revision to Diff 558160.Thu, Nov 23, 7:20 AM
xingxue marked 6 inline comments as done.

Addressed comments.

  • use __void_t instead of defining void_t
  • rename test case to libcxx/test/libcxx/utilities/function.objects/refwrap/argument_types.verify
  • rename test function from int main to void test
  • test reference_wrapper<int> and verify compile time errors from typedefs of its argument_type and other members
xingxue added inline comments.Thu, Nov 23, 7:22 AM
libcxx/include/__functional/weak_result_type.h
67–68

Changed as suggested, thanks!

70

Changed as suggested, thanks!

101

Can we fix std::mem_fn and other similar functions in a separate PR later? (working another item)

libcxx/test/libcxx/utilities/function.objects/refwrap/refwrap_types.pass.cpp
1

Changed the file name to libcxx/test/libcxx/utilities/function.objects/refwrap/argument_types.verify.cpp because the test now also verifies compile time errors.

24

Changed as suggested, thanks!

27

Added tests for reference_wrapper<int> and verify compile time errors from its argument_type and other typedefs.

libcxx/test/std/depr/depr.function.objects/depr.base/refwrap_types.depr.verify.cpp
9–13

Done, thanks!