Tested on fmtlib trunk downloaded at 2022-06-29. The following complete code leads to a compiler error for Visual Studio compilers (Tested for VS 2019 and VS 2022 targeting C++17):
#include "fmt/ranges.h"
#include "fmt/std.h"
int main()
{
std::filesystem::path p("data/somewhat");
fmt::format("Path={}", p);
}
The produced error is:
1>XXX\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\type_traits(593,1): error C2752: 'fmt::v8::formatter<std::filesystem::path,char,void>': more than one partial specialization matches the template argument list
1>XXX\fmt-master\include\fmt\ranges.h(396,1): message : could be 'fmt::v8::formatter<R,Char,std::enable_if<fmt::v8::is_range<T,Char>::value,void>::type>'
1>XXX\fmt-master\include\fmt\std.h(54,1): message : or 'fmt::v8::formatter<std::filesystem::path,Char,void>'
1>XXX\fmt-master\include\fmt\core.h(1485): message : see reference to class template instantiation 'std::is_constructible<fmt::v8::formatter<std::filesystem::path,char,void>>' being compiled
1>XXX\fmt-master\include\fmt\core.h(1679): message : see reference to alias template instantiation 'fmt::v8::detail::mapped_type_constant<std::filesystem::path,fmt::v8::format_context>' being compiled
1>XXX\fmt-master\include\fmt\core.h(1840): message : see reference to function template instantiation 'unsigned __int64 fmt::v8::detail::encode_types<Context,std::filesystem::path,>(void)' being compiled
1> with
1> [
1> Context=fmt::v8::format_context
1> ]
1>XXX\fmt-master\include\fmt\core.h(3224): message : see reference to class template instantiation 'fmt::v8::format_arg_store<fmt::v8::format_context,std::filesystem::path>' being compiled
1>XXX\Cpp\vs2019\fmtlib-composition\fmt-issue.cpp(7): message : see reference to function template instantiation 'void fmt::v8::print<std::filesystem::path&>(fmt::v8::basic_format_string<char,std::filesystem::path &>,std::filesystem::path &)' being compiled
1>XXX\fmt-master\include\fmt\core.h(1678): error C2062: type 'unknown-type' unexpected
1>XXX\fmt-master\include\fmt\core.h(1678): error C2144: syntax error: 'unknown-type' should be preceded by '('
1>XXX\fmt-master\include\fmt\core.h(1679,68): error C2039: 'value': is not a member of '`global namespace''
1>XXX\fmt-master\include\fmt\core.h(1837,56): error C3615: constexpr function 'fmt::v8::detail::encode_types' cannot result in a constant expression
1>XXX\fmt-master\include\fmt\core.h(1840): message : failure was caused by control reaching the end of a constexpr function
I'm aware that the problem does not occur for gcc or clang, the most likely reason is the special exclusion code involving
in ranges.h#L401, but we really need to support VS 2019 for quite a while. The reason for that workaround code is not quite clear to me, but it is possible as a workaround even in the presence of this workaround to replace the partial specialization in std.h#L54 by two specializations
template <>
struct formatter<std::filesystem::path, char>;
template <>
struct formatter<std::filesystem::path, wchar_t>;
to solve the issue.
The issue is rather severe, because it happens quite often that you need both ranges.h and std.h in the same translation unit.
I recommend to add at least the here described code as test case regardless of the actual solution.
I'd like to point out that we stumbled across this problem when we borrowed the technique described in issue 2778 but using the same partial template specialization technique that is used in std.h, so this also likely happens if user-code attempts to adopt the technique described in that issue.
I'm open to make a corresponding pull request, but would like to get feedback on the preferred resolution.
Tested on fmtlib trunk downloaded at 2022-06-29. The following complete code leads to a compiler error for Visual Studio compilers (Tested for VS 2019 and VS 2022 targeting C++17):
The produced error is:
I'm aware that the problem does not occur for gcc or clang, the most likely reason is the special exclusion code involving
in ranges.h#L401, but we really need to support VS 2019 for quite a while. The reason for that workaround code is not quite clear to me, but it is possible as a workaround even in the presence of this workaround to replace the partial specialization in std.h#L54 by two specializations
to solve the issue.
The issue is rather severe, because it happens quite often that you need both
ranges.handstd.hin the same translation unit.I recommend to add at least the here described code as test case regardless of the actual solution.
I'd like to point out that we stumbled across this problem when we borrowed the technique described in issue 2778 but using the same partial template specialization technique that is used in
std.h, so this also likely happens if user-code attempts to adopt the technique described in that issue.I'm open to make a corresponding pull request, but would like to get feedback on the preferred resolution.