-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Conversation
@Dani-Hub |
…tter specializations for ranges and maps more robust (especially for Visual Studio compiler family)
…td::filesystem::path> partial template specialization into two explicit specialization.
There was a problem hiding this 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.
include/fmt/core.h
Outdated
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 { | ||
}; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
test/CMakeLists.txt
Outdated
@@ -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) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); | |||
} | |||
}; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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+?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
…ion would cause an ambiguity error
… conditionals for filesystem::path testing that does not run into the ambiguity problem.
Can someone explain to me the red cross that occurs now at my revised changes in |
Merged, thanks! |
Thanks for the review and guidance! |
PULL request for issue #2954