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

Fix partial specialization problem for filesystem for Visual Studio #2957

Merged
merged 7 commits into from
Jul 3, 2022

Conversation

Dani-Hub
Copy link
Contributor

@Dani-Hub Dani-Hub commented Jul 2, 2022

PULL request for issue #2954

@phprus
Copy link
Contributor

phprus commented Jul 2, 2022

@Dani-Hub
Please resolve merge conflicts.

…tter specializations for ranges and maps more robust (especially for Visual Studio compiler family)
…td::filesystem::path> partial template specialization into two explicit specialization.
Copy link
Contributor

@vitaut vitaut left a comment

Choose a reason for hiding this comment

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

Thanks for the PR.

Comment on lines 295 to 306
template <typename...>
struct disjunction;
template <>
struct disjunction<> : std::false_type {};
template <typename P>
struct disjunction<P> : P {};
template <typename P1, typename P2>
struct disjunction<P1, P2> : std::conditional<P1::value, P1, P2>::type {};
template <typename P1, typename P2, typename P3, typename... Pn>
struct disjunction<P1, P2, P3, Pn...>
: std::conditional<P1::value, P1, disjunction<P2, P3, Pn...>>::type {
};
Copy link
Contributor

@vitaut vitaut Jul 3, 2022

Choose a reason for hiding this comment

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

Why not use a simpler implementation like the one from cppreference?

template<class...> struct disjunction : std::false_type { };
template<class B1> struct disjunction<B1> : B1 { };
template<class B1, class... Bn>
struct disjunction<B1, Bn...> 
    : std::conditional_t<bool(B1::value), B1, disjunction<Bn...>>  { };

And the same for conjunction.

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 suggested the current implementation, because it is the same one that I committed for libstdc++ years ago and that worked for all known compilers regardless of completeness of variadic templates and minor rule changes in variadic templates. That being said, I guess the suggested alternative will work for all supported compilers. While adjusting this, we also can add a minor compile-conditional regarding __cpp_lib_logical_traits and take advantage of the STL variant in this case.

Copy link
Contributor

Choose a reason for hiding this comment

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

we also can add a minor compile-conditional regarding __cpp_lib_logical_traits and take advantage of the STL variant in this case.

I suggest keeping it simple and not introducing conditional compilation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK.

@@ -78,13 +78,15 @@ add_fmt_test(printf-test)
add_fmt_test(ranges-test ranges-odr-test.cc)
add_fmt_test(scan-test)
add_fmt_test(std-test)
add_fmt_test(ranges-std-test)
Copy link
Contributor

@vitaut vitaut Jul 3, 2022

Choose a reason for hiding this comment

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

Please merge this into std-test. Having a separate binary for a single test case is an overkill and including fmt/ranges.h from std-test is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Are you really sure that you want that? This means that your preexisting test does not actually test anymore that the inclusion of stl.h suffices to get the wanted effects, it only tests that the combined inclusion has these effects. I really recommend to keep the separate test translation unit, because this introduces exactly the errornous situation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are you really sure that you want that?

Yes. Just make sure to keep fmt/std.h as the first include. I'm not concerned about other interactions between headers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -69,6 +70,33 @@ struct formatter<std::filesystem::path, Char>
basic_string_view<Char>(quoted.data(), quoted.size()), ctx);
}
};
Copy link
Contributor

@vitaut vitaut Jul 3, 2022

Choose a reason for hiding this comment

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

I don't think the above conditional branch is needed because character types other than char and wchar_t won't work anyway.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are you writing about a generic implementation?
Why?
path::string<Char>() (and path formatter) supports char, wchar_t, char8_t, char16_t, and char32_t types.

Copy link
Contributor

@vitaut vitaut Jul 3, 2022

Choose a reason for hiding this comment

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

Ah, you are right. string<Char>() does the magic. In this case I suggest keeping just the generic branch and not introducing a workaround for broken msvc 2017. If anyone wants to format a path on a broken compiler version they can always use .string(). And 2019+ will work with the other workaround.

Copy link
Contributor Author

@Dani-Hub Dani-Hub Jul 3, 2022

Choose a reason for hiding this comment

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

At least according to std::format specification only char and wchar_t are supported for charT, that's the reason for my suggested workaround in this case. According to my experience, MSVC 2017 is still heavily in use. If you still prefer giving up 2017 support, may I suggest then a revised solution that still detects the problematic MSVC version and does not provide the partial specialization in this case? Regardless of that decision the corresponding test needs to get an extra conditional anyway.

Copy link
Contributor

Choose a reason for hiding this comment

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

If you still prefer giving up 2017 support, may I suggest then a revised solution that still detects the problematic MSVC version and does not provide the partial specialization in this case?

Yes, I think it's better to disable path support on an older broken compiler completely rather than enable it partially for some character types. Detecting the problematic MSVC version sounds reasonable but maybe move it to a separate PR and leave this one to fixing 2019+?

Copy link
Contributor Author

@Dani-Hub Dani-Hub Jul 3, 2022

Choose a reason for hiding this comment

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

I'm not suggesting to disable path support unconditionally. I'm suggesting to enable it conditionally for all cases that we know to work, so effectively not providing any specialization if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920.
The same conditional will need to be added to the ranges-std test anyway, so why providing functionality that we decide to not test, because it does not work? Does that make sense to you?

Copy link
Contributor

@vitaut vitaut Jul 3, 2022

Choose a reason for hiding this comment

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

which value would it have to keep the partial specialization without conditional?

It will keep the implementation simple if I understood your question correctly. We generally try to avoid conditional compilation unless absolutely necessary and limiting it to test significantly reduces the scope.

Also:

it's better to disable path support on an older broken compiler completely rather than enable it partially for some character types

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's better to disable path support on an older broken compiler completely rather than enable it partially for some character types

My revised solution wasn't suggesting to enable it partially for some character types.

Copy link
Contributor

Choose a reason for hiding this comment

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

The revised solution seems OK to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@Dani-Hub
Copy link
Contributor Author

Dani-Hub commented Jul 3, 2022

Can someone explain to me the red cross that occurs now at my revised changes in core.h and std.h?

@vitaut vitaut merged commit d2a2320 into fmtlib:master Jul 3, 2022
@vitaut
Copy link
Contributor

vitaut commented Jul 3, 2022

Merged, thanks!

@Dani-Hub
Copy link
Contributor Author

Dani-Hub commented Jul 3, 2022

Thanks for the review and guidance!

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

Successfully merging this pull request may close these issues.

None yet

3 participants