This is an archive of the discontinued LLVM Phabricator instance.

Add is_nothrow_convertible (P0758R1)
ClosedPublic

Authored by zoecarver on Feb 10 2019, 5:07 PM.

Details

Summary

Add both is_nothrow_convertible and is_nothrow_convertible_v according to P0758R1.

Diff Detail

Event Timeline

zoecarver created this revision.Feb 10 2019, 5:07 PM
ldionne requested changes to this revision.Feb 11 2019, 9:06 AM
ldionne added a reviewer: ldionne.
ldionne added inline comments.
include/type_traits
1594

Should be __is_nothrow_convertible_helper instead.

test/libcxx/type_traits/is_nothrow_convertible.pass.cpp
2 ↗(On Diff #186171)

This should be test/std/type_traits/is_nothrow_convertible.pass.cpp because it's not a libc++ specific behavior.

31 ↗(On Diff #186171)

Those should be static_asserts.

41 ↗(On Diff #186171)

You have tests where To and From are complete types. Please add tests for:

  • cv void types
  • arrays of unknown bounds
  • arrays of known bounds
  • function types

Actually, I'm looking at this and std::is_convertible again, and I think this should be using std::is_convertible in the implementation. I know the paper suggests the implementation in this patch, however it's unclear to me whether that implementation properly handles all the cases that std::is_convertible handles (notably with references). Also, using std::is_convertible under the hood means that we will use the __is_convertible_to intrinsic when it's available instead.

I would do something like this instead (untested):

template <typename _Fm, typename _To>
struct __is_nothrow_convertible_impl {
private:
    template <typename _Tp>
    static void __test_noexcept(_Tp) noexcept;
    
    template<typename __Fm, typename __To>
    static bool_constant<noexcept(__test_noexcept<__To>(declval<__Fm>()))>
    __test(int);
    
    template<typename, typename>
    static false_type
    __test(...);
    
public:
    using type = decltype(__test<_Fm, _To>(0));
};

template <typename _Fm, typename _To>
struct is_nothrow_convertible : __and_<is_convertible<_Fm, _To>, __is_nothrow_convertible_impl<_Fm, _To>>
{ };

This is very similar to what you have, but I also guard the whole thing with std::is_convertible. What do you think? Did I miss a subtlety that would make my draft implementation wrong (that's quite possible)?

zoecarver marked 4 inline comments as done.Feb 11 2019, 10:56 AM

@ldionne That looks good. I played around with using std::conditional for a while but I think your implementation is the cleanest.

ldionne requested changes to this revision.Feb 12 2019, 9:37 AM
ldionne added inline comments.
include/type_traits
1591

I don't think this is useful anymore, as this should be handled by std::is_convertible. IOW, I think only the test for noexcept-ness of the conversion needs to exist, not for convertibility.

This revision now requires changes to proceed.Feb 12 2019, 9:37 AM
zoecarver marked 2 inline comments as done.Feb 12 2019, 10:04 AM
zoecarver added inline comments.
include/type_traits
1591

Good catch, you're completely right. In fact, we could probably simplify this a lot and just have it use is_nothrow_constructible<_Fm, _To>. I am a bit hesitant to do that because it isn't what is_nothrow_constructible's intended use is, what do you think?

zoecarver marked an inline comment as done.Feb 12 2019, 10:31 AM
zoecarver added inline comments.
include/type_traits
1591

Actually correction: void will not work in the below __test_noexcept method so it has to have its own overload. But I can get rid of the is_array/is_function checks (because those will be caught by std::is_convertible).

@ldionne just for reference, this is what it would look like to use is_nothrow_constructible:

template <typename _Fm, typename _To>
struct is_nothrow_convertible : __and_<
    is_convertible<_Fm, _To>,
    __libcpp_is_nothrow_constructible<true, true, _Fm, _To>
>::type { };

@ldionne just for reference, this is what it would look like to use is_nothrow_constructible:

template <typename _Fm, typename _To>
struct is_nothrow_convertible : __and_<
    is_convertible<_Fm, _To>,
    __libcpp_is_nothrow_constructible<true, true, _Fm, _To>
>::type { };

Right -- I'd rather we reimplement the checking ourselves instead of relying on __libcpp_is_nothrow_constructible<true, true, _Fm, _To> (where we'd be lying about the reference-ness of _To.

include/type_traits
1591

Makes sense, see my suggestion below. I don't think we can use is_nothrow_constructible, since the check for non-reference types is:

integral_constant<bool, noexcept(_Tp(declval<_Args>()...))>

That's not checking whether the conversion operator is noexcept, only a constructor.

1619

How about this:

__or<
  __and_<is_void<_Fm>, is_void<_To>>,
  __and<is_convertible<_Fm, _To>, __is_nothrow_convertible_helper<_Fm, _To>>
>

And then __is_nothrow_convertible_helper doesn't have to care about void.

zoecarver marked 3 inline comments as done.Feb 12 2019, 10:55 AM

Sounds good, that is probably the better call.

include/type_traits
1591

Fair point, didn't think about that.

1619

Thanks @ldionne, that is great. After all the tests pass I will upload the new patch.

zoecarver marked an inline comment as done.
ldionne requested changes to this revision.Feb 13 2019, 12:03 PM

This is looking better and better.

include/type_traits
1596

The rule is usually 1 underscore followed by a capital letter, or 2 underscores followed by a small letter. For template parameters, we use the former. Here you have 2 underscores followed by a capital.

This is pedantic, but since you're a new contributor, we might as well start on the right foot.

1597

You can hoist this helper function and its friend above outside of the class. This way you don't get an instantiation of __test_noexcept<_Tp> for each pair of _To and _From, only one for each type. You'll still get an instantiation of __test for each pair of _To and _From, but at least you don't need to play games with the names of the template parameters if you hoist the function outside the class.

1600

I don't think you need this overload anymore. Indeed, you already know that _Fm is convertible to _To because you checked with std::is_convertible.

test/std/type_traits/is_nothrow_convertible.pass.cpp
16

I think you don't need this header.

This revision now requires changes to proceed.Feb 13 2019, 12:03 PM
zoecarver marked 7 inline comments as done.Feb 13 2019, 12:38 PM

Thanks for all the help :)

include/type_traits
1597

Good idea. I also simply inherit from decltype instead of having the type member. Much cleaner.

1600

Your right.

test/std/type_traits/is_nothrow_convertible.pass.cpp
16

Correct.

zoecarver marked 3 inline comments as done.

@ldionne Friendly ping I think this is done?

ldionne requested changes to this revision.Feb 26 2019, 3:19 PM

Sorry, I was at a Committee meeting. It looks like you need to update the synopsis comment at the top of file, and also update cxx2a_status.html. But I think this looks good apart from that.

This revision now requires changes to proceed.Feb 26 2019, 3:19 PM
zoecarver updated this revision to Diff 188498.Feb 26 2019, 8:19 PM

Update synopsis comment and www.

@ldionne No worries, hope the committee meeting went well. Fixed both of those. This patch was definitely the most fun to write :)

ldionne added inline comments.Feb 27 2019, 9:02 AM
include/type_traits
149

Use From and To here too. Also, please add a // C++17 comment for both of them.

zoecarver marked an inline comment as done.Feb 27 2019, 9:19 AM
zoecarver added inline comments.
include/type_traits
149

// C++20, right?

zoecarver updated this revision to Diff 188569.Feb 27 2019, 9:23 AM

Fix comment (// C++20 and To/From)

ldionne accepted this revision.Feb 27 2019, 9:48 AM
ldionne added inline comments.
include/type_traits
149

Uh, yes. Oops.

This revision is now accepted and ready to land.Feb 27 2019, 9:48 AM
ldionne closed this revision.Feb 27 2019, 9:57 AM

Committed as r355010.

Thanks for the patch!

test/std/type_traits/is_nothrow_convertible.pass.cpp
51

Watch for trailing whitespace like this (I removed it when applying the patch). You can probably configure your editor to remove it automatically.

zoecarver marked an inline comment as done.Feb 27 2019, 10:41 AM

@ldionne Awesome! Thank you for the help.

test/std/type_traits/is_nothrow_convertible.pass.cpp
51

Thank you, I will keep an eye out for these.