Skip to content

Conversation

@miscco
Copy link
Contributor

@miscco miscco commented Feb 5, 2021

This works towards adding a packed basic_format_arg_store

It is almost fully functional, however some things are missing:

  1. I did not yet include the handle constriants as I focussed on getting the basic types right
  2. We should use a smaller unsigned type for the _Format_arg_store_packed_index
  3. When writing this the default format_context definitions were not available

@miscco miscco requested a review from a team as a code owner February 5, 2021 12:40
@AdamBucior

This comment has been minimized.

@miscco
Copy link
Contributor Author

miscco commented Feb 5, 2021

Note I did not test the value of the arguments

@miscco miscco changed the base branch from main to feature/format February 5, 2021 12:59
Copy link
Contributor Author

@miscco miscco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this go to format branch?

Yeah, I messed up, should be correct now

Comment on lines 349 to 351
if (_Id >= _Num_args) {
_You_see_this_error_because_arg_id_is_out_of_range();
}
Copy link
Contributor

@CaseyCarter CaseyCarter Feb 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be _STL_VERIFY(_Id < _Num_args, "No, silly - don't do that")?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am totally fine with anything that gets the job done and helps the user understand the error

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afaik the reason libfmt doesn't do this check unconditionally at runtime is that it gets caught later on anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, is STL_VERIFY always active and how does the codegen compare against a simple function call?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks to me like STL_VERIFY is always enabled (and STL_ASSERT expands to it in debug mode)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what I do not like, is that the STL_VERIFY error message is really bad from an error reporting stand point.

It essentially first complains about wassert and you do not get the full error message.

In contrast that function would be always directly flagged by the compiler.

Note that nothing happens during runtime right now. If we want to change that STL_VERIFY would make more sense

void _Store(const size_t _Arg_index, basic_string<_CharType, _Traits, _Alloc> _Val) noexcept {
_Store_impl<basic_string_view<_CharType>, _Basic_format_arg_type::_String_type>(
_Arg_index, _Basic_format_arg_type::_String_type, basic_string_view<_CharType>{_Val.data(), _Val.size()});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that the previous two functions are overloads because they need to deduce the parameters of basic_string_view/basic_string, but it seems the overloads that take float/double/long double/const _CharType*/nullptr_t could be part of the if constexpr stack in the first overload.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they are depicted as overloads in the standard, I'm not actually sure why.

I suppose the floating point overloads can be used even if the formatter associated with float/double/long double doesn't meat the formatter requirements.

This comment was marked as outdated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved arithmetic types to their own function

stl/inc/format Outdated
// clang-format off
template <class _Ty>
requires is_void_v<_Ty>
void _Store(const size_t _Arg_index, const _Ty* p) noexcept {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function intended to accept something other than void* and const void*? If not, could it simply be a non-template that takes const void*? If it's intended to accept volatile void* and const volatile void*, the static_cast on 641 is ill-formed (static_cast can't cast away cv-qualifiers).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think It is explicitly made to prevent volatile and discriminate between string literals.

That said I do not know why it was given in the standard like that https://eel.is/c++draft/format#arg-12

: _Index(static_cast<_Index_type>(_Index)), _Type(_Basic_format_arg_type::_None) {}

_Index_type _Index : (sizeof(_Index_type) * 8 - 4);
_Basic_format_arg_type _Type : 4;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to self: this is better than
{
data[]
offset[]
tag[]
}
because tag is half a byte and this way we don't pull in useless tags when we load the one we want

Copy link
Contributor Author

@miscco miscco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self we are missing enums

stl/inc/format Outdated
Comment on lines 576 to 577
byte _Storage[(_STD max)(_Storage_length, 1ull)];
_Index_type _Index_array[(_STD max)(_Num_args, 1ull)];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is essentially equivalent to the standards variant array

we just move the _Index member of the variant into its own array.

That said I think we should move to a type erased storage struct, and pass a pointer to that to basic_format_args.

That way we would only need one pointer rather than two

stl/inc/format Outdated
} else if constexpr (signed_integral<_Ty> && sizeof(_Ty) <= sizeof(int)) {
_Store_impl<int, _Basic_format_arg_type::_Int_type>(_Arg_index, static_cast<int>(_Val));
} else if constexpr (unsigned_integral<_Ty> && sizeof(_Ty) <= sizeof(unsigned)) {
_Store_impl<unsigned, _Basic_format_arg_type::_UInt_type>(_Arg_index, static_cast<unsigned>(_Val));

This comment was marked as resolved.

void _Store(const size_t _Arg_index, basic_string<_CharType, _Traits, _Alloc> _Val) noexcept {
_Store_impl<basic_string_view<_CharType>, _Basic_format_arg_type::_String_type>(
_Arg_index, _Basic_format_arg_type::_String_type, basic_string_view<_CharType>{_Val.data(), _Val.size()});
}

This comment was marked as outdated.

@miscco miscco force-pushed the format_store branch 3 times, most recently from b360a5f to 971b137 Compare February 7, 2021 21:23
@barcharcraz barcharcraz self-assigned this Feb 10, 2021
@barcharcraz barcharcraz merged commit a52214a into microsoft:feature/format Feb 12, 2021
@miscco miscco deleted the format_store branch February 12, 2021 14:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cxx20 C++20 feature format C++20/23 format

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants