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

vformat_to_n(char *) fails to compile with GCC 8. #2149

Closed
toojays opened this issue Feb 24, 2021 · 1 comment · Fixed by #2160
Closed

vformat_to_n(char *) fails to compile with GCC 8. #2149

toojays opened this issue Feb 24, 2021 · 1 comment · Fixed by #2160

Comments

@toojays
Copy link
Contributor

toojays commented Feb 24, 2021

Consider the following example of formatting to a fixed size buffer before writing to stdout:

#include <fmt/format.h>
#include <unistd.h>

void vlog(fmt::string_view format, fmt::format_args args) {
  char line[1024];
  auto [_, size] = fmt::vformat_to_n(line, sizeof(line), format, args);
  write(STDOUT_FILENO, line, size);
}

template <typename S, typename... Args>
void log(const S& format, Args&&... args) {
  vlog(format, fmt::make_args_checked<Args...>(format, args...));
}

int main() {
  log("invalid squishiness: {}", 42);
}

With GCC 9 and 10 this works. But with GCC 8 this fails to compile (godbolt) with:

<source>: In function 'void vlog(fmt::v7::string_view, fmt::v7::format_args)':
<source>:6:70: error: no matching function for call to 'vformat_to_n(char [1024], long unsigned int, fmt::v7::string_view&, fmt::v7::format_args&)'
   auto [_, size] = fmt::vformat_to_n(line, sizeof(line), format, args);
                                                                      ^
In file included from /opt/compiler-explorer/libs/fmt/trunk/include/fmt/format.h:46,
                 from <source>:1:
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:1830:37: note: candidate: 'template<class OutputIt, class Char, class ... Args, typename std::enable_if<fmt::v7::detail::is_output_iterator<OutputIt, Char>::value, int>::type <anonymous> > fmt::v7::format_to_n_result<OutputIt> fmt::v7::vformat_to_n(OutputIt, size_t, fmt::v7::basic_string_view<Char>, fmt::v7::basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<typename fmt::v7::type_identity<Char>::type>, typename fmt::v7::type_identity<Char>::type> >)'
 inline format_to_n_result<OutputIt> vformat_to_n(
                                     ^~~~~~~~~~~~
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:1830:37: note:   template argument deduction/substitution failed:
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:1829:11: error: no type named 'type' in 'struct std::enable_if<false, int>'
           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
           ^~~~~~~~~~~~~
ASM generation compiler returned: 1
<source>: In function 'void vlog(fmt::v7::string_view, fmt::v7::format_args)':
<source>:6:70: error: no matching function for call to 'vformat_to_n(char [1024], long unsigned int, fmt::v7::string_view&, fmt::v7::format_args&)'
   auto [_, size] = fmt::vformat_to_n(line, sizeof(line), format, args);
                                                                      ^
In file included from /opt/compiler-explorer/libs/fmt/trunk/include/fmt/format.h:46,
                 from <source>:1:
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:1830:37: note: candidate: 'template<class OutputIt, class Char, class ... Args, typename std::enable_if<fmt::v7::detail::is_output_iterator<OutputIt, Char>::value, int>::type <anonymous> > fmt::v7::format_to_n_result<OutputIt> fmt::v7::vformat_to_n(OutputIt, size_t, fmt::v7::basic_string_view<Char>, fmt::v7::basic_format_args<fmt::v7::basic_format_context<fmt::v7::detail::buffer_appender<typename fmt::v7::type_identity<Char>::type>, typename fmt::v7::type_identity<Char>::type> >)'
 inline format_to_n_result<OutputIt> vformat_to_n(
                                     ^~~~~~~~~~~~
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:1830:37: note:   template argument deduction/substitution failed:
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:1829:11: error: no type named 'type' in 'struct std::enable_if<false, int>'
           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
           ^~~~~~~~~~~~~

Unfortunately GCC 8 is still relevant to me as it is the most recent upstream-built compiler for Red Hat / CentOS 6 (via devtoolset-8).

@alexezeder
Copy link
Contributor

Looks like GCC 8.x is the only compiler that fails with the current implementation of void_t - https://godbolt.org/z/zbK5q3.

fmt/include/fmt/core.h

Lines 1382 to 1385 in 640acba

// A workaround for gcc 4.8 to make void_t work in a SFINAE context.
template <typename... Ts> struct void_t_impl { using type = void; };
template <typename... Ts>
using void_t = typename detail::void_t_impl<Ts...>::type;

But this failure on GCC 8 can be solved by removing that workaround for GCC 4.8-4.9 and using straightforward implementation - https://godbolt.org/z/v4q8P6.

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 a pull request may close this issue.

2 participants