This is an archive of the discontinued LLVM Phabricator instance.

[libcxx] adds std::identity to <functional>
ClosedPublic

Authored by cjdb on Mar 7 2021, 1:10 PM.

Details

Summary

Implements parts of:

  • P0898R3 Standard Library Concepts

Diff Detail

Event Timeline

cjdb requested review of this revision.Mar 7 2021, 1:10 PM
cjdb created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptMar 7 2021, 1:10 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript
cjdb added subscribers: CaseyCarter, mclow.lists.
cjdb added inline comments.
libcxx/include/functional
3073

Will add this line back in on commit or next arc diff.

curdeius requested changes to this revision.Mar 7 2021, 1:24 PM
curdeius added inline comments.
libcxx/include/functional
3222

is_transparent member type seems to be missing.

This revision now requires changes to proceed.Mar 7 2021, 1:24 PM
cjdb updated this revision to Diff 328904.Mar 7 2021, 1:54 PM

applies @curdeius' feedback

cjdb marked an inline comment as done.Mar 7 2021, 1:54 PM
Quuxplusone added inline comments.Mar 7 2021, 5:37 PM
libcxx/include/functional
221

Please move this up to directly after bit_not (and before unary_negate).
The synopses of the bitwise operators were all cut-and-paste-typoed; I just pushed a fix (changing comments only) so now there is a bit_not to put this after. :)

libcxx/test/std/utilities/function.objects/func.identity/identity.pass.cpp
44

Please, as @ldionne would say, "add some simple tests." :)
I think given the simplicity of std::identity, the entire test suite for it should look like this:

#include "support/moveonly.h"

constexpr bool test() {
    std::identity id;
    int i = 42;
    assert(id(i) == 42);
    assert(id(std::move(i)) == 42);

    MoveOnly m1 = 2;
    MoveOnly m2 = id(std::move(m1));
    assert(m2.value == 2);

    assert(&id(i) == &i);
    assert(&id(std::move(i)) == &i);
    assert(&id(std::move(m1) == &m1);
    static_assert(&id(id) == &id);

    const std::identity idc;
    assert(idc(1) == 1);
    assert(std::move(id)(1) == 1);
    assert(std::move(idc)(1) == 1);

    id = idc;  // test assignability

    static_assert(std::is_same_v<decltype(id(i)), int&>);
    static_assert(std::is_same_v<decltype(id(std::declval<int&&>())), int&&>);
    static_assert(std::is_same_v<decltype(id(std::declval<const int&>)), const int&>);
    static_assert(std::is_same_v<decltype(id(std::declval<const int&&>)), const int&&>);
    static_assert(std::is_same_v<decltype(id(std::declval<volatile int&>)), volatile int&>);
    static_assert(std::is_same_v<decltype(id(std::declval<volatile int&&>)), volatile int&&>);

    return true;
}

int main(int, char**) {
    test();
    static_assert(test());

    return 0;
}

I don't think the test suite should depend on C++20 nor concepts. I don't think we need any more lines of test code than what I've written here.

Quuxplusone requested changes to this revision.Mar 7 2021, 5:37 PM
This revision now requires changes to proceed.Mar 7 2021, 5:37 PM
Quuxplusone added inline comments.Mar 7 2021, 5:44 PM
libcxx/test/std/utilities/function.objects/func.identity/identity.pass.cpp
44

...well, and also a test that std::identity::is_transparent is a typename.

static_assert(std::is_same_v<std::void_t<std::identity::is_transparent>, void>);

should do the trick.

curdeius resigned from this revision.Mar 8 2021, 12:47 AM
Mordante added inline comments.Mar 11 2021, 9:40 AM
libcxx/include/functional
221

Please add comment that this has been added in C++20.

3224

Can you add a test that this function is noexcept?

libcxx/test/std/utilities/function.objects/func.identity/identity.pass.cpp
44

@Quuxplusone The feature is C++20 so we can't drop that, but I agree with the concepts.
Since it's unspecified what is_transparent is I think it would be better not to test it's value. Doesn't the test at line 23 already test what you want?

@cjdb I'm also in favour of a simpler test for this feature.

libcxx/test/std/utilities/function.objects/func.identity/identity.pass.cpp
44

Since it's unspecified what is_transparent is I think it would be better not to test its value.

I agree; note the void_t in my suggestion. I believe this accomplishes the "it must be a type but I don't care what type it is" goal.

And this plays into my "not depend on C++20" request. The test on line 23 does test what I want, but it uses C++20 core-language Concepts features to do it. I prefer my suggestion because it doesn't depend on the compiler to implement C++20 Concepts; in that sense I'm requesting a "C++17 test for a C++20 library feature." I know we can't remove UNSUPPORTED: c++17; I just think it's cleaner to use the more "basic" language features anywhere we can. For the same reason, my proposed test cases use e.g. std::is_same_v<decltype(id(i)), int&> and not std::same_as<decltype(id(i)), int&>.

Mordante added inline comments.Mar 11 2021, 10:43 AM
libcxx/test/std/utilities/function.objects/func.identity/identity.pass.cpp
44

My bad I missed the void_t.

Thanks for the additional information. I agree with your point.

EricWF added inline comments.Mar 18 2021, 10:31 AM
libcxx/test/std/utilities/function.objects/func.identity/identity.pass.cpp
24

Is the type required to be void? If so, add a test.

112

Do we the defaulted comparison operator here? I would rather not depend on yet another new language feature that we don't need too.

EricWF accepted this revision.Mar 18 2021, 10:41 AM

LGTM after addressing the current inline comments.
Please make sure the other reviewers don't have any unresolved comments before submitting.

Quuxplusone requested changes to this revision.Mar 18 2021, 10:45 AM

@cjdb: I am willing to commandeer this revision for the purpose of replacing the test file with my "simpler test" above (and then I'd be responsible for watching buildkite and landing it). Let me know if you want me to do that.
Alternatively, you don't have to do exactly what I pasted above, but IMNSHO the tests really need to be shorter and simpler somehow.

cjdb updated this revision to Diff 333613.Mar 26 2021, 1:08 PM

After checking that no coverage is lost, I've adopted @Quuxplusone's suggested test with minor changes. There are still two concept tests, since I think both of those are simpler than the alternative.

LGTM modulo the two unaddressed comments I see: "move the mention in the synopsis" and "add a test for noexceptness" (which I've taken the liberty of drafting).

libcxx/include/functional
3224

+1

struct X { X(const X&); X(X&&); };
void test_noexcept() {
    X x;
    static_assert(noexcept(id(x)));
    static_assert(noexcept(id(X()));
};
cjdb updated this revision to Diff 333689.Mar 27 2021, 3:05 PM
cjdb marked 4 inline comments as done.

applies final bit of feedback

cjdb marked an inline comment as done.Mar 27 2021, 3:06 PM
cjdb added inline comments.
libcxx/test/std/utilities/function.objects/func.identity/identity.pass.cpp
112

I think per @Quuxplusone's changes, this comment is outdated.

Quuxplusone accepted this revision.Mar 29 2021, 6:07 AM
This revision is now accepted and ready to land.Mar 29 2021, 6:07 AM
This revision was automatically updated to reflect the committed changes.
cjdb marked an inline comment as done.