Add both is_nothrow_convertible and is_nothrow_convertible_v according to P0758R1.
Details
Diff Detail
Event Timeline
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:
|
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)?
@ldionne That looks good. I played around with using std::conditional for a while but I think your implementation is the cleanest.
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. |
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? |
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 { };
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. |
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. |
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.
@ldionne No worries, hope the committee meeting went well. Fixed both of those. This patch was definitely the most fun to write :)
include/type_traits | ||
---|---|---|
149 | Use From and To here too. Also, please add a // C++17 comment for both of them. |
include/type_traits | ||
---|---|---|
149 | // C++20, right? |
include/type_traits | ||
---|---|---|
149 | Uh, yes. Oops. |
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. |
Use From and To here too. Also, please add a // C++17 comment for both of them.