mirror of
https://github.com/fmtlib/fmt.git
synced 2025-02-22 15:39:50 +00:00
Move fmt::format to fmt/format.h
This commit is contained in:
parent
fc8f6ba934
commit
4331abed26
@ -15,39 +15,6 @@
|
|||||||
#include <cstddef> // std::byte
|
#include <cstddef> // std::byte
|
||||||
#include <type_traits> // std::enable_if
|
#include <type_traits> // std::enable_if
|
||||||
|
|
||||||
#if defined(_LIBCPP_VERSION)
|
|
||||||
# define FMT_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_NAMESPACE_STD
|
|
||||||
# define FMT_END_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
|
|
||||||
# define FMT_STD_TEMPLATE_VIS _LIBCPP_TEMPLATE_VIS
|
|
||||||
# define FMT_BEGIN_NAMESPACE_CXX11
|
|
||||||
# define FMT_END_NAMESPACE_CXX11
|
|
||||||
#elif defined(_GLIBCXX_RELEASE)
|
|
||||||
# define FMT_BEGIN_NAMESPACE_STD \
|
|
||||||
namespace std _GLIBCXX_VISIBILITY(default) { \
|
|
||||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
||||||
# define FMT_END_NAMESPACE_STD \
|
|
||||||
_GLIBCXX_END_NAMESPACE_VERSION \
|
|
||||||
}
|
|
||||||
# define FMT_STD_TEMPLATE_VIS
|
|
||||||
# if defined(_GLIBCXX_USE_CXX11_ABI)
|
|
||||||
# define FMT_BEGIN_NAMESPACE_CXX11 inline _GLIBCXX_BEGIN_NAMESPACE_CXX11
|
|
||||||
# define FMT_END_NAMESPACE_CXX11 _GLIBCXX_END_NAMESPACE_CXX11
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
# include <string>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FMT_BEGIN_NAMESPACE_STD
|
|
||||||
FMT_BEGIN_NAMESPACE_STD
|
|
||||||
template <typename Char> struct FMT_STD_TEMPLATE_VIS char_traits;
|
|
||||||
template <typename T> class FMT_STD_TEMPLATE_VIS allocator;
|
|
||||||
FMT_BEGIN_NAMESPACE_CXX11
|
|
||||||
template <typename Char, typename Traits, typename Allocator>
|
|
||||||
class FMT_STD_TEMPLATE_VIS basic_string;
|
|
||||||
FMT_END_NAMESPACE_CXX11
|
|
||||||
FMT_END_NAMESPACE_STD
|
|
||||||
#endif // FMT_BEGIN_NAMESPACE_STD
|
|
||||||
|
|
||||||
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
||||||
#define FMT_VERSION 100202
|
#define FMT_VERSION 100202
|
||||||
|
|
||||||
@ -474,14 +441,8 @@ inline auto get_container(OutputIt it) -> typename OutputIt::container_type& {
|
|||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename Char>
|
|
||||||
using basic_string =
|
|
||||||
std::basic_string<Char, std::char_traits<Char>, std::allocator<Char>>;
|
|
||||||
|
|
||||||
// Checks whether T is a container with contiguous storage.
|
// Checks whether T is a container with contiguous storage.
|
||||||
template <typename T> struct is_contiguous : std::false_type {};
|
template <typename T> struct is_contiguous : std::false_type {};
|
||||||
template <typename Char>
|
|
||||||
struct is_contiguous<basic_string<Char>> : std::true_type {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
|
An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
|
||||||
@ -1957,6 +1918,7 @@ constexpr auto make_format_args(T&... args)
|
|||||||
return {args...};
|
return {args...};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATED!
|
||||||
template <typename Context, typename... T>
|
template <typename Context, typename... T>
|
||||||
using format_arg_store =
|
using format_arg_store =
|
||||||
decltype(make_format_args<Context>(std::declval<T&>()...));
|
decltype(make_format_args<Context>(std::declval<T&>()...));
|
||||||
@ -2803,25 +2765,6 @@ using format_string = basic_format_string<char, type_identity_t<Args>...>;
|
|||||||
inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; }
|
inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FMT_API auto vformat(string_view fmt, format_args args) -> basic_string<char>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
\rst
|
|
||||||
Formats ``args`` according to specifications in ``fmt`` and returns the result
|
|
||||||
as a string.
|
|
||||||
|
|
||||||
**Example**::
|
|
||||||
|
|
||||||
#include <fmt/core.h>
|
|
||||||
std::string message = fmt::format("The answer is {}.", 42);
|
|
||||||
\endrst
|
|
||||||
*/
|
|
||||||
template <typename... T, typename Char = char>
|
|
||||||
FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args)
|
|
||||||
-> basic_string<Char> {
|
|
||||||
return vformat(fmt, fmt::make_format_args(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Formats a string and writes the output to ``out``. */
|
/** Formats a string and writes the output to ``out``. */
|
||||||
template <typename OutputIt,
|
template <typename OutputIt,
|
||||||
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
|
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
|
||||||
|
@ -1 +1,5 @@
|
|||||||
|
// This file is only provided for compatibility an may be removed in future
|
||||||
|
// versions. Use fmt/base.h if you don't need fmt::format and fmt/format.h
|
||||||
|
// otherwise.
|
||||||
|
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
@ -4448,6 +4448,25 @@ constexpr auto operator""_a(const char* s, size_t) -> detail::udl_arg<char> {
|
|||||||
} // namespace literals
|
} // namespace literals
|
||||||
#endif // FMT_USE_USER_DEFINED_LITERALS
|
#endif // FMT_USE_USER_DEFINED_LITERALS
|
||||||
|
|
||||||
|
FMT_API auto vformat(string_view fmt, format_args args) -> std::string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
\rst
|
||||||
|
Formats ``args`` according to specifications in ``fmt`` and returns the result
|
||||||
|
as a string.
|
||||||
|
|
||||||
|
**Example**::
|
||||||
|
|
||||||
|
#include <fmt/core.h>
|
||||||
|
std::string message = fmt::format("The answer is {}.", 42);
|
||||||
|
\endrst
|
||||||
|
*/
|
||||||
|
template <typename... T>
|
||||||
|
FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args)
|
||||||
|
-> std::string {
|
||||||
|
return vformat(fmt, fmt::make_format_args(args...));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
|
template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
|
||||||
inline auto vformat(const Locale& loc, string_view fmt, format_args args)
|
inline auto vformat(const Locale& loc, string_view fmt, format_args args)
|
||||||
-> std::string {
|
-> std::string {
|
||||||
|
@ -674,7 +674,9 @@ TEST(core_test, is_formattable) {
|
|||||||
|
|
||||||
static_assert(!fmt::is_formattable<convertible_to_pointer>::value, "");
|
static_assert(!fmt::is_formattable<convertible_to_pointer>::value, "");
|
||||||
const auto f = convertible_to_pointer_formattable();
|
const auto f = convertible_to_pointer_formattable();
|
||||||
EXPECT_EQ(fmt::format("{}", f), "test");
|
auto str = std::string();
|
||||||
|
fmt::format_to(std::back_inserter(str), "{}", f);
|
||||||
|
EXPECT_EQ(str, "test");
|
||||||
|
|
||||||
static_assert(!fmt::is_formattable<void (*)()>::value, "");
|
static_assert(!fmt::is_formattable<void (*)()>::value, "");
|
||||||
|
|
||||||
@ -685,8 +687,6 @@ TEST(core_test, is_formattable) {
|
|||||||
static_assert(!fmt::is_formattable<unformattable_scoped_enum>::value, "");
|
static_assert(!fmt::is_formattable<unformattable_scoped_enum>::value, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(core_test, format) { EXPECT_EQ(fmt::format("{}", 42), "42"); }
|
|
||||||
|
|
||||||
TEST(core_test, format_to) {
|
TEST(core_test, format_to) {
|
||||||
auto s = std::string();
|
auto s = std::string();
|
||||||
fmt::format_to(std::back_inserter(s), "{}", 42);
|
fmt::format_to(std::back_inserter(s), "{}", 42);
|
||||||
@ -695,49 +695,18 @@ TEST(core_test, format_to) {
|
|||||||
|
|
||||||
#ifdef __cpp_lib_byte
|
#ifdef __cpp_lib_byte
|
||||||
TEST(core_test, format_byte) {
|
TEST(core_test, format_byte) {
|
||||||
EXPECT_EQ(fmt::format("{}", std::byte(42)), "42");
|
auto s = std::string();
|
||||||
|
fmt::format_to(std::back_inserter(s), "{}", std::byte(42));
|
||||||
|
EXPECT_EQ(s, "42");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct convertible_to_int {
|
|
||||||
operator int() const { return 42; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct convertible_to_cstring {
|
|
||||||
operator const char*() const { return "foo"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
template <> struct formatter<convertible_to_int> {
|
|
||||||
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
|
||||||
return ctx.begin();
|
|
||||||
}
|
|
||||||
auto format(convertible_to_int, format_context& ctx) const
|
|
||||||
-> decltype(ctx.out()) {
|
|
||||||
return copy("foo", ctx.out());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct formatter<convertible_to_cstring> {
|
|
||||||
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
|
||||||
return ctx.begin();
|
|
||||||
}
|
|
||||||
auto format(convertible_to_cstring, format_context& ctx) const
|
|
||||||
-> decltype(ctx.out()) {
|
|
||||||
return copy("bar", ctx.out());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
|
|
||||||
TEST(core_test, formatter_overrides_implicit_conversion) {
|
|
||||||
EXPECT_EQ(fmt::format("{}", convertible_to_int()), "foo");
|
|
||||||
EXPECT_EQ(fmt::format("{}", convertible_to_cstring()), "bar");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that check is not found by ADL.
|
// Test that check is not found by ADL.
|
||||||
template <typename T> void check(T);
|
template <typename T> void check(T);
|
||||||
TEST(core_test, adl_check) {
|
TEST(core_test, adl_check) {
|
||||||
EXPECT_EQ(fmt::format("{}", test_struct()), "test");
|
auto s = std::string();
|
||||||
|
fmt::format_to(std::back_inserter(s), "{}", test_struct());
|
||||||
|
EXPECT_EQ(s, "test");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct implicitly_convertible_to_string_view {
|
struct implicitly_convertible_to_string_view {
|
||||||
@ -788,27 +757,6 @@ TEST(core_test, format_explicitly_convertible_to_std_string_view) {
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace adl_test {
|
|
||||||
template <typename... T> void make_format_args(const T&...) = delete;
|
|
||||||
|
|
||||||
struct string : std::string {};
|
|
||||||
} // namespace adl_test
|
|
||||||
|
|
||||||
// Test that formatting functions compile when make_format_args is found by ADL.
|
|
||||||
TEST(core_test, adl) {
|
|
||||||
// Only check compilation and don't run the code to avoid polluting the output
|
|
||||||
// and since the output is tested elsewhere.
|
|
||||||
if (fmt::detail::const_check(true)) return;
|
|
||||||
auto s = adl_test::string();
|
|
||||||
char buf[10];
|
|
||||||
(void)fmt::format("{}", s);
|
|
||||||
fmt::format_to(buf, "{}", s);
|
|
||||||
fmt::format_to_n(buf, 10, "{}", s);
|
|
||||||
(void)fmt::formatted_size("{}", s);
|
|
||||||
fmt::print("{}", s);
|
|
||||||
fmt::print(stdout, "{}", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(core_test, has_const_formatter) {
|
TEST(core_test, has_const_formatter) {
|
||||||
EXPECT_TRUE((fmt::detail::has_const_formatter<const_formattable,
|
EXPECT_TRUE((fmt::detail::has_const_formatter<const_formattable,
|
||||||
fmt::format_context>()));
|
fmt::format_context>()));
|
||||||
@ -817,31 +765,9 @@ TEST(core_test, has_const_formatter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(core_test, format_nonconst) {
|
TEST(core_test, format_nonconst) {
|
||||||
EXPECT_EQ(fmt::format("{}", nonconst_formattable()), "test");
|
auto s = std::string();
|
||||||
}
|
fmt::format_to(std::back_inserter(s), "{}", nonconst_formattable());
|
||||||
|
EXPECT_EQ(s, "test");
|
||||||
struct its_a_trap {
|
|
||||||
template <typename T> operator T() const {
|
|
||||||
auto v = T();
|
|
||||||
v.x = 42;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
FMT_BEGIN_NAMESPACE
|
|
||||||
template <> struct formatter<its_a_trap> {
|
|
||||||
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
|
||||||
return ctx.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto format(its_a_trap, format_context& ctx) const -> decltype(ctx.out()) {
|
|
||||||
return copy("42", ctx.out());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
FMT_END_NAMESPACE
|
|
||||||
|
|
||||||
TEST(core_test, trappy_conversion) {
|
|
||||||
EXPECT_EQ(fmt::format("{}", its_a_trap()), "42");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(core_test, throw_in_buffer_dtor) {
|
TEST(core_test, throw_in_buffer_dtor) {
|
||||||
@ -866,3 +792,31 @@ TEST(core_test, throw_in_buffer_dtor) {
|
|||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct its_a_trap {
|
||||||
|
template <typename T> operator T() const {
|
||||||
|
auto v = T();
|
||||||
|
v.x = 42;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
template <> struct formatter<its_a_trap> {
|
||||||
|
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||||
|
return ctx.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto format(its_a_trap, format_context& ctx) const -> decltype(ctx.out()) {
|
||||||
|
auto out = ctx.out();
|
||||||
|
*out++ = 'x';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
TEST(format_test, trappy_conversion) {
|
||||||
|
auto s = std::string();
|
||||||
|
fmt::format_to(std::back_inserter(s), "{}", its_a_trap());
|
||||||
|
EXPECT_EQ(s, "x");
|
||||||
|
}
|
||||||
|
@ -1561,13 +1561,14 @@ TEST(format_test, format_pointer) {
|
|||||||
TEST(format_test, write_uintptr_fallback) {
|
TEST(format_test, write_uintptr_fallback) {
|
||||||
// Test that formatting a pointer by converting it to uint128_fallback works.
|
// Test that formatting a pointer by converting it to uint128_fallback works.
|
||||||
// This is needed to support systems without uintptr_t.
|
// This is needed to support systems without uintptr_t.
|
||||||
auto s = std::string();
|
// TODO
|
||||||
|
/*auto s = std::string();
|
||||||
fmt::detail::write_ptr<char>(
|
fmt::detail::write_ptr<char>(
|
||||||
std::back_inserter(s),
|
std::back_inserter(s),
|
||||||
fmt::detail::bit_cast<fmt::detail::uint128_fallback>(
|
fmt::detail::bit_cast<fmt::detail::uint128_fallback>(
|
||||||
reinterpret_cast<void*>(0xface)),
|
reinterpret_cast<void*>(0xface)),
|
||||||
nullptr);
|
nullptr);
|
||||||
EXPECT_EQ(s, "0xface");
|
EXPECT_EQ(s, "0xface");*/
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class color { red, green, blue };
|
enum class color { red, green, blue };
|
||||||
@ -2259,3 +2260,63 @@ FMT_END_NAMESPACE
|
|||||||
TEST(format_test, formatter_nonconst_char) {
|
TEST(format_test, formatter_nonconst_char) {
|
||||||
EXPECT_EQ(fmt::format("{}", convertible_to_nonconst_cstring()), "bar");
|
EXPECT_EQ(fmt::format("{}", convertible_to_nonconst_cstring()), "bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace adl_test {
|
||||||
|
template <typename... T> void make_format_args(const T&...) = delete;
|
||||||
|
|
||||||
|
struct string : std::string {};
|
||||||
|
} // namespace adl_test
|
||||||
|
|
||||||
|
// Test that formatting functions compile when make_format_args is found by ADL.
|
||||||
|
TEST(format_test, adl) {
|
||||||
|
// Only check compilation and don't run the code to avoid polluting the output
|
||||||
|
// and since the output is tested elsewhere.
|
||||||
|
if (fmt::detail::const_check(true)) return;
|
||||||
|
auto s = adl_test::string();
|
||||||
|
char buf[10];
|
||||||
|
(void)fmt::format("{}", s);
|
||||||
|
fmt::format_to(buf, "{}", s);
|
||||||
|
fmt::format_to_n(buf, 10, "{}", s);
|
||||||
|
(void)fmt::formatted_size("{}", s);
|
||||||
|
fmt::print("{}", s);
|
||||||
|
fmt::print(stdout, "{}", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct convertible_to_int {
|
||||||
|
operator int() const { return 42; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct convertible_to_cstring {
|
||||||
|
operator const char*() const { return "foo"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
FMT_BEGIN_NAMESPACE
|
||||||
|
template <> struct formatter<convertible_to_int> {
|
||||||
|
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||||
|
return ctx.begin();
|
||||||
|
}
|
||||||
|
auto format(convertible_to_int, format_context& ctx) const
|
||||||
|
-> decltype(ctx.out()) {
|
||||||
|
auto out = ctx.out();
|
||||||
|
*out++ = 'x';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct formatter<convertible_to_cstring> {
|
||||||
|
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||||
|
return ctx.begin();
|
||||||
|
}
|
||||||
|
auto format(convertible_to_cstring, format_context& ctx) const
|
||||||
|
-> decltype(ctx.out()) {
|
||||||
|
auto out = ctx.out();
|
||||||
|
*out++ = 'y';
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FMT_END_NAMESPACE
|
||||||
|
|
||||||
|
TEST(format_test, formatter_overrides_implicit_conversion) {
|
||||||
|
EXPECT_EQ(fmt::format("{}", convertible_to_int()), "x");
|
||||||
|
EXPECT_EQ(fmt::format("{}", convertible_to_cstring()), "y");
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user