Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test enforce-checks-test.cc fails after implementing P2499 #3030

Closed
strega-nil-ms opened this issue Aug 9, 2022 · 11 comments
Closed

Test enforce-checks-test.cc fails after implementing P2499 #3030

strega-nil-ms opened this issue Aug 9, 2022 · 11 comments

Comments

@strega-nil-ms
Copy link

Hi! Friendly neighborhood STL implementor here 😸

After implementing P2499R0 in microsoft/STL#2947, the test enforce-checks-test now fails.

Compiler output
C:\Users\nimazzuc\projects\fmt\include\fmt\core.h(2742): error C2039: 'parse': is not a member of 'fmt::v9::detail::fallback_formatter<stripped_type,char_type,void>'
C:\Users\nimazzuc\projects\fmt\include\fmt\core.h(2741): note: see declaration of 'fmt::v9::detail::fallback_formatter<stripped_type,char_type,void>'
C:\Users\nimazzuc\projects\fmt\include\fmt\core.h(2947): note: see reference to function template instantiation 'const char *fmt::v9::detail::parse_format_specs<std::vector<char,std::allocator<char>>,fmt::v9::detail::compile_parse_context<Char,ErrorHandler>>(ParseContext &)' being compiled
        with
        [
            Char=char,
            ErrorHandler=fmt::v9::detail::error_handler,
            ParseContext=fmt::v9::detail::compile_parse_context<char,fmt::v9::detail::error_handler>
        ]
C:\Users\nimazzuc\projects\fmt\include\fmt\core.h(2947): note: while compiling class template member function 'fmt::v9::detail::format_string_checker<Char,fmt::v9::detail::error_handler,std::vector<char,std::allocator<char>>>::format_string_checker(fmt::v9::basic_string_view<Char>,ErrorHandler)'
        with
        [
            Char=char,
            ErrorHandler=fmt::v9::detail::error_handler
        ]
C:\Users\nimazzuc\projects\fmt\include\fmt\core.h(3141): note: see reference to class template instantiation 'fmt::v9::detail::format_string_checker<Char,fmt::v9::detail::error_handler,std::vector<char,std::allocator<char>>>' being compiled
        with
        [
            Char=char
        ]
.\test\enforce-checks-test.cc(55): note: see reference to function template instantiation 'fmt::v9::basic_format_string<char,std::vector<char,std::allocator<char>> &>::basic_format_string<test_range::<lambda_1>::()::FMT_COMPILE_STRING,0>(const S &)' being compiled
        with
        [
            S=test_range::<lambda_1>::()::FMT_COMPILE_STRING
        ]

Before, it worked because basic_string_view<char> was convertible from any contiguous range of char; now, it is only constructible from any contiguous range of char.

@vitaut
Copy link
Contributor

vitaut commented Aug 9, 2022

This is surprising because vector<char> doesn't need to be convertible to string_view to be formattable as a range of chars. See e.g. https://godbolt.org/z/4oPK6dxM5.

@strega-nil-ms
Copy link
Author

Yeah, I dunno; I think the metaprogramming is broken somehow, but it slipped under the radar because vector<char> was convertible to string_view

@QuellaZhang
Copy link

Any updates or patch for this?

@vitaut
Copy link
Contributor

vitaut commented Aug 22, 2022

I don't have a windows machine at hand and the issue doesn't repro on godbolt. If someone is able to repro and can investigate this issue it would be appreciated.

@strega-nil-ms
Copy link
Author

So, interestingly, it does work for vector<int>, but not for vector<char>:

#include <fmt/format.h>
#include <fmt/ranges.h>
#include <vector>

using namespace std;

int main() {
  vector<CHAR_OR_INT> hello{'h', 'e', 'l', 'l', 'o'};
  fmt::print("{}\n", hello);
}

works when -DCHAR_OR_INT=int, but doesn't when -DCHAR_OR_INT=char

@strega-nil-ms
Copy link
Author

It looks like vector<char> is not considered a range for some reason:

#include <fmt/format.h>
#include <fmt/ranges.h>
#include <vector>

using namespace std;

int main() {
  static_assert(fmt::is_range<vector<char>, char>::value); // FAILS
  static_assert(fmt::is_range<vector<int>, char>::value); // SUCCEEDS
}

@strega-nil-ms
Copy link
Author

strega-nil-ms commented Aug 23, 2022

I think I figured out the problem:

template <typename T, typename Char> struct is_range {
  static constexpr const bool value =
      detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
      !std::is_convertible<T, std::basic_string<Char>>::value &&
      !std::is_constructible<detail::std_string_view<Char>, T>::value; // <--- problem
};

string_view is constructible from vector<char>, but vector<char> is not implicitly convertible to string_view; therefore, vector<char> is not a range, but because it's not convertible, it doesn't get formatted as a string_view either.

(I think this may be the issue in #3050)

@vitaut
Copy link
Contributor

vitaut commented Aug 26, 2022

Thanks for investigating, @strega-nil-ms. Does e4f4fc7 fix the issue?

@strega-nil-ms
Copy link
Author

strega-nil-ms commented Aug 26, 2022

@vitaut it should, but it's still incorrect - what you have is

   static constexpr const bool value =
       detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
       !std::is_convertible<T, std::basic_string<Char>>::value &&
-      !std::is_constructible<detail::std_string_view<Char>, T>::value;
+      !std::is_convertible<detail::std_string_view<Char>, T>::value;

but what you want is

   static constexpr const bool value =
       detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
       !std::is_convertible<T, std::basic_string<Char>>::value &&
-      !std::is_constructible<detail::std_string_view<Char>, T>::value;
+      !std::is_convertible<T, detail::std_string_view<Char>>::value;

note the different parameter ordering of is_constructible and is_convertible

@vitaut
Copy link
Contributor

vitaut commented Aug 26, 2022

the different parameter ordering of is_constructible and is_convertible

Ugh.

Thanks!

@vitaut
Copy link
Contributor

vitaut commented Aug 26, 2022

Should be fixed in 4a8e294.

@vitaut vitaut closed this as completed Aug 26, 2022
mtremer pushed a commit to ipfire/ipfire-2.x that referenced this issue Nov 28, 2022
- Update from version 9.0.0 to 9.1.0
- Update of rootfile
- Changelog
    9.1.0 - 2022-08-27
	* ``fmt::formatted_size`` now works at compile time
		  `#3026 <https://github.com/fmtlib/fmt/pull/3026>`_
			  For example (`godbolt <https://godbolt.org/z/1MW5rMdf8>`__):
			   .. code:: c++
			     #include <fmt/compile.h>
			     int main() {
			       using namespace fmt::literals;
			       constexpr size_t n = fmt::formatted_size("{}"_cf, 42);
			       fmt::print("{}\n", n); // prints 2
			     }
	* Fixed handling of invalid UTF-8
		  `#3038 <https://github.com/fmtlib/fmt/pull/3038>`_,
		  `#3044 <https://github.com/fmtlib/fmt/pull/3044>`_,
		  `#3056 <https://github.com/fmtlib/fmt/pull/3056>`_
	* Improved Unicode support in ``ostream`` overloads of ``print``
		  `#2994 <https://github.com/fmtlib/fmt/pull/2994>`_,
		  `#3001 <https://github.com/fmtlib/fmt/pull/3001>`_,
		  `#3025 <https://github.com/fmtlib/fmt/pull/3025>`_
	* Fixed handling of the sign specifier in localized formatting on systems with
	   32-bit ``wchar_t``
		  `#3041 <https://github.com/fmtlib/fmt/issues/3041>`_).
	* Added support for wide streams to ``fmt::streamed``
		  `#2994 <https://github.com/fmtlib/fmt/pull/2994>`_
	* Added the ``n`` specifier that disables the output of delimiters when
	   formatting ranges
		  `#2981 <https://github.com/fmtlib/fmt/pull/2981>`_,
		  `#2983 <https://github.com/fmtlib/fmt/pull/2983>`_
			  For example (`godbolt <https://godbolt.org/z/roKqGdj8c>`__):
			   .. code:: c++
			     #include <fmt/ranges.h>
			     #include <vector>
			     int main() {
			       auto v = std::vector{1, 2, 3};
			       fmt::print("{:n}\n", v); // prints 1, 2, 3
			     }
	* Worked around problematic ``std::string_view`` constructors introduced in C++23
		  `#3030 <https://github.com/fmtlib/fmt/issues/3030>`_,
		  `#3050 <https://github.com/fmtlib/fmt/issues/3050>`_
	* Improve handling (exclusion) of recursive ranges
		  `#2968 <https://github.com/fmtlib/fmt/issues/2968>`_,
		  `#2974 <https://github.com/fmtlib/fmt/pull/2974>`_
	* Improved error reporting in format string compilation
		  `#3055 <https://github.com/fmtlib/fmt/issues/3055>`_
	* Improved the implementation of
		  `Dragonbox <https://github.com/jk-jeon/dragonbox>`_, the algorithm used for
		   the default floating-point formatting
		  `#2984 <https://github.com/fmtlib/fmt/pull/2984>`_
	* Fixed issues with floating-point formatting on exotic platforms.
	* Improved the implementation of chrono formatting
		  `#3010 <https://github.com/fmtlib/fmt/pull/3010>`_
	* Improved documentation
		  `#2966 <https://github.com/fmtlib/fmt/pull/2966>`_,
		  `#3009 <https://github.com/fmtlib/fmt/pull/3009>`_,
		  `#3020 <https://github.com/fmtlib/fmt/issues/3020>`_,
		  `#3037 <https://github.com/fmtlib/fmt/pull/3037>`_
	* Improved build configuration
		  `#2991 <https://github.com/fmtlib/fmt/pull/2991>`_,
		  `#2995 <https://github.com/fmtlib/fmt/pull/2995>`_,
		  `#3004 <https://github.com/fmtlib/fmt/issues/3004>`_,
		  `#3007 <https://github.com/fmtlib/fmt/pull/3007>`_,
		  `#3040 <https://github.com/fmtlib/fmt/pull/3040>`_
	* Fixed various warnings and compilation issues
		  `#2969 <https://github.com/fmtlib/fmt/issues/2969>`_,
		  `#2971 <https://github.com/fmtlib/fmt/pull/2971>`_,
		  `#2975 <https://github.com/fmtlib/fmt/issues/2975>`_,
		  `#2982 <https://github.com/fmtlib/fmt/pull/2982>`_,
		  `#2985 <https://github.com/fmtlib/fmt/pull/2985>`_,
		  `#2988 <https://github.com/fmtlib/fmt/issues/2988>`_,
		  `#3000 <https://github.com/fmtlib/fmt/issues/3000>`_,
		  `#3006 <https://github.com/fmtlib/fmt/issues/3006>`_,
		  `#3014 <https://github.com/fmtlib/fmt/issues/3014>`_,
		  `#3015 <https://github.com/fmtlib/fmt/issues/3015>`_,
		  `#3021 <https://github.com/fmtlib/fmt/pull/3021>`_,
		  `#3023 <https://github.com/fmtlib/fmt/issues/3023>`_,
		  `#3024 <https://github.com/fmtlib/fmt/pull/3024>`_,
		  `#3029 <https://github.com/fmtlib/fmt/pull/3029>`_,
		  `#3043 <https://github.com/fmtlib/fmt/pull/3043>`_,
		  `#3052 <https://github.com/fmtlib/fmt/issues/3052>`_,
		  `#3053 <https://github.com/fmtlib/fmt/pull/3053>`_,
		  `#3054 <https://github.com/fmtlib/fmt/pull/3054>`_

Signed-off-by: Adolf Belka <adolf.belka@ipfire.org>
Reviewed-by: Michael Tremer <michael.tremer@ipfire.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants