-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Closed
Labels
fixedSomething works now, yay!Something works now, yay!throughputMust compile fasterMust compile faster
Description
<__msvc_int128.hpp> spends a hundred lines defining a lot of machinery to implement UDLs:
Lines 1423 to 1524 in 0098818
| inline namespace literals { | |
| inline namespace _Int128_literals { | |
| namespace _Int128_detail { | |
| enum class _U128_parse_status : unsigned char { | |
| _Valid, | |
| _Overflow, | |
| _Invalid, | |
| }; | |
| struct _U128_parse_result { | |
| _U128_parse_status _Status_code; | |
| _Unsigned128 _Value; | |
| }; | |
| _NODISCARD _CONSTEVAL unsigned int _Char_to_digit(const char _Ch) noexcept { | |
| if (_Ch >= '0' && _Ch <= '9') { | |
| return static_cast<unsigned int>(_Ch - '0'); | |
| } | |
| if (_Ch >= 'A' && _Ch <= 'F') { | |
| return static_cast<unsigned int>(_Ch - 'A' + 10); | |
| } | |
| if (_Ch >= 'a' && _Ch <= 'f') { | |
| return static_cast<unsigned int>(_Ch - 'a' + 10); | |
| } | |
| return static_cast<unsigned int>(-1); | |
| } | |
| template <unsigned int _Base, char... _Chars> | |
| struct _Parse_u128_impl { | |
| _NODISCARD static _CONSTEVAL _U128_parse_result _Parse() noexcept { | |
| if constexpr (sizeof...(_Chars) == 0) { | |
| return {_U128_parse_status::_Valid, 0}; | |
| } else { | |
| constexpr char _Char_seq[]{_Chars...}; | |
| constexpr auto _U128_max = (numeric_limits<_Unsigned128>::max)(); | |
| _Unsigned128 _Val{}; | |
| for (const char _Ch : _Char_seq) { | |
| if (_Ch == '\'') { | |
| continue; | |
| } | |
| const unsigned int _Digit = _Char_to_digit(_Ch); | |
| if (_Digit == static_cast<unsigned int>(-1)) { | |
| return {_U128_parse_status::_Invalid, _Unsigned128{}}; | |
| } | |
| if (_Val > _U128_max / _Base || _Base * _Val > _U128_max - _Digit) { | |
| return {_U128_parse_status::_Overflow, _Unsigned128{}}; | |
| } | |
| _Val = _Base * _Val + _Digit; | |
| } | |
| return {_U128_parse_status::_Valid, _Val}; | |
| } | |
| } | |
| }; | |
| template <char... _Chars> | |
| struct _Parse_u128 : _Parse_u128_impl<10, _Chars...> {}; | |
| template <char... _Chars> | |
| struct _Parse_u128<'0', 'X', _Chars...> : _Parse_u128_impl<16, _Chars...> {}; | |
| template <char... _Chars> | |
| struct _Parse_u128<'0', 'x', _Chars...> : _Parse_u128_impl<16, _Chars...> {}; | |
| template <char... _Chars> | |
| struct _Parse_u128<'0', 'B', _Chars...> : _Parse_u128_impl<2, _Chars...> {}; | |
| template <char... _Chars> | |
| struct _Parse_u128<'0', 'b', _Chars...> : _Parse_u128_impl<2, _Chars...> {}; | |
| template <char... _Chars> | |
| struct _Parse_u128<'0', _Chars...> : _Parse_u128_impl<8, _Chars...> {}; | |
| } // namespace _Int128_detail | |
| template <char... _Chars> | |
| _NODISCARD _CONSTEVAL _Unsigned128 operator"" __u128() noexcept { | |
| constexpr auto _Parsed_result = _Int128_detail::_Parse_u128<_Chars...>::_Parse(); | |
| static_assert(_Parsed_result._Status_code != _Int128_detail::_U128_parse_status::_Invalid, | |
| "Invalid characters in the integer literal"); | |
| static_assert(_Parsed_result._Status_code != _Int128_detail::_U128_parse_status::_Overflow, | |
| "The integer literal is too large for an unsigned 128-bit number"); | |
| return _Parsed_result._Value; | |
| } | |
| template <char... _Chars> | |
| _NODISCARD _CONSTEVAL _Signed128 operator"" __i128() noexcept { | |
| constexpr auto _Parsed_result = _Int128_detail::_Parse_u128<_Chars...>::_Parse(); | |
| static_assert(_Parsed_result._Status_code != _Int128_detail::_U128_parse_status::_Invalid, | |
| "Invalid characters in the integer literal"); | |
| static_assert(_Parsed_result._Status_code != _Int128_detail::_U128_parse_status::_Overflow | |
| && _Parsed_result._Value._Word[1] < (static_cast<uint64_t>(1) << 63), | |
| "The integer literal is too large for a signed 128-bit number"); | |
| return static_cast<_Signed128>(_Parsed_result._Value); | |
| } | |
| } // namespace _Int128_literals | |
| } // namespace literals |
These UDLs aren't used by product code at all. They're used by only one test (where they are indeed quite useful):
| using namespace std::literals::_Int128_literals; |
We typically don't define internal machinery in product code that's used only by test code, as this has a throughput cost. (Separately, this is triggering a /clr compiler bug, VSO-1673940 DevCom-10195454 "managed C++ 17.5 error C2049: 'std::literals::_Int128_literals': non-inline namespace cannot be reopened as inline".)
I believe that we should move these UDLs into the test.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
fixedSomething works now, yay!Something works now, yay!throughputMust compile fasterMust compile faster