Commit 418659ad authored by Victor Zverovich's avatar Victor Zverovich

Fix compilation errors on gcc 4.4

parent 1d2adef2
...@@ -167,6 +167,11 @@ ...@@ -167,6 +167,11 @@
# define FMT_USE_EXPERIMENTAL_STRING_VIEW # define FMT_USE_EXPERIMENTAL_STRING_VIEW
#endif #endif
// std::result_of is defined in <functional> in gcc 4.4.
#if FMT_GCC_VERSION && FMT_GCC_VERSION <= 404
# include <functional>
#endif
namespace fmt { namespace fmt {
// An implementation of declval for pre-C++11 compilers such as gcc 4. // An implementation of declval for pre-C++11 compilers such as gcc 4.
...@@ -302,8 +307,6 @@ class basic_buffer { ...@@ -302,8 +307,6 @@ class basic_buffer {
std::size_t capacity_; std::size_t capacity_;
protected: protected:
typedef const T &const_reference;
basic_buffer(T *p = FMT_NULL, std::size_t size = 0, std::size_t capacity = 0) basic_buffer(T *p = FMT_NULL, std::size_t size = 0, std::size_t capacity = 0)
FMT_NOEXCEPT: ptr_(p), size_(size), capacity_(capacity) {} FMT_NOEXCEPT: ptr_(p), size_(size), capacity_(capacity) {}
...@@ -322,6 +325,7 @@ class basic_buffer { ...@@ -322,6 +325,7 @@ class basic_buffer {
public: public:
typedef T value_type; typedef T value_type;
typedef const T &const_reference;
virtual ~basic_buffer() {} virtual ~basic_buffer() {}
...@@ -655,6 +659,16 @@ enum { MAX_PACKED_ARGS = 15 }; ...@@ -655,6 +659,16 @@ enum { MAX_PACKED_ARGS = 15 };
template <typename Context> template <typename Context>
class arg_map; class arg_map;
template <typename>
struct result_of;
template <typename F, typename... Args>
struct result_of<F(Args...)> {
// A workaround for gcc 4.4 that doesn't allow F to be a reference.
typedef typename std::result_of<
typename std::remove_reference<F>::type(Args...)>::type type;
};
} }
// A formatting argument. It is a trivially copyable/constructible type to // A formatting argument. It is a trivially copyable/constructible type to
...@@ -669,7 +683,7 @@ class basic_arg { ...@@ -669,7 +683,7 @@ class basic_arg {
friend FMT_CONSTEXPR basic_arg<ContextType> internal::make_arg(const T &value); friend FMT_CONSTEXPR basic_arg<ContextType> internal::make_arg(const T &value);
template <typename Visitor, typename Ctx> template <typename Visitor, typename Ctx>
friend FMT_CONSTEXPR typename std::result_of<Visitor(int)>::type friend FMT_CONSTEXPR typename internal::result_of<Visitor(int)>::type
visit(Visitor &&vis, basic_arg<Ctx> arg); visit(Visitor &&vis, basic_arg<Ctx> arg);
friend class basic_format_args<Context>; friend class basic_format_args<Context>;
......
This diff is collapsed.
...@@ -61,8 +61,8 @@ class convert_to_int<T, Char, true> { ...@@ -61,8 +61,8 @@ class convert_to_int<T, Char, true> {
private: private:
template <typename U> template <typename U>
static decltype( static decltype(
std::declval<test_stream<Char>&>() << std::declval<U>(), std::true_type()) internal::declval<test_stream<Char>&>()
test(int); << internal::declval<U>(), std::true_type()) test(int);
template <typename> template <typename>
static std::false_type test(...); static std::false_type test(...);
......
...@@ -19,7 +19,7 @@ namespace internal { ...@@ -19,7 +19,7 @@ namespace internal {
// Checks if a value fits in int - used to avoid warnings about comparing // Checks if a value fits in int - used to avoid warnings about comparing
// signed and unsigned integers. // signed and unsigned integers.
template <bool IsSigned> template <bool IsSigned>
struct IntChecker { struct int_checker {
template <typename T> template <typename T>
static bool fits_in_int(T value) { static bool fits_in_int(T value) {
unsigned max = std::numeric_limits<int>::max(); unsigned max = std::numeric_limits<int>::max();
...@@ -29,7 +29,7 @@ struct IntChecker { ...@@ -29,7 +29,7 @@ struct IntChecker {
}; };
template <> template <>
struct IntChecker<true> { struct int_checker<true> {
template <typename T> template <typename T>
static bool fits_in_int(T value) { static bool fits_in_int(T value) {
return value >= std::numeric_limits<int>::min() && return value >= std::numeric_limits<int>::min() &&
...@@ -38,12 +38,12 @@ struct IntChecker<true> { ...@@ -38,12 +38,12 @@ struct IntChecker<true> {
static bool fits_in_int(int) { return true; } static bool fits_in_int(int) { return true; }
}; };
class PrintfPrecisionHandler { class printf_precision_handler: public function<int> {
public: public:
template <typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value, int>::type typename std::enable_if<std::is_integral<T>::value, int>::type
operator()(T value) { operator()(T value) {
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
FMT_THROW(format_error("number is too big")); FMT_THROW(format_error("number is too big"));
return static_cast<int>(value); return static_cast<int>(value);
} }
...@@ -57,7 +57,7 @@ class PrintfPrecisionHandler { ...@@ -57,7 +57,7 @@ class PrintfPrecisionHandler {
}; };
// An argument visitor that returns true iff arg is a zero integer. // An argument visitor that returns true iff arg is a zero integer.
class IsZeroInt { class is_zero_int: public function<bool> {
public: public:
template <typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type typename std::enable_if<std::is_integral<T>::value, bool>::type
...@@ -77,7 +77,7 @@ struct make_unsigned_or_bool<bool> { ...@@ -77,7 +77,7 @@ struct make_unsigned_or_bool<bool> {
}; };
template <typename T, typename Context> template <typename T, typename Context>
class ArgConverter { class arg_converter: public function<void> {
private: private:
typedef typename Context::char_type Char; typedef typename Context::char_type Char;
...@@ -85,7 +85,7 @@ class ArgConverter { ...@@ -85,7 +85,7 @@ class ArgConverter {
typename Context::char_type type_; typename Context::char_type type_;
public: public:
ArgConverter(basic_arg<Context> &arg, Char type) arg_converter(basic_arg<Context> &arg, Char type)
: arg_(arg), type_(type) {} : arg_(arg), type_(type) {}
void operator()(bool value) { void operator()(bool value) {
...@@ -134,19 +134,19 @@ class ArgConverter { ...@@ -134,19 +134,19 @@ class ArgConverter {
// unsigned). // unsigned).
template <typename T, typename Context, typename Char> template <typename T, typename Context, typename Char>
void convert_arg(basic_arg<Context> &arg, Char type) { void convert_arg(basic_arg<Context> &arg, Char type) {
visit(ArgConverter<T, Context>(arg, type), arg); visit(arg_converter<T, Context>(arg, type), arg);
} }
// Converts an integer argument to char for printf. // Converts an integer argument to char for printf.
template <typename Context> template <typename Context>
class CharConverter { class char_converter: public function<void> {
private: private:
basic_arg<Context> &arg_; basic_arg<Context> &arg_;
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); FMT_DISALLOW_COPY_AND_ASSIGN(char_converter);
public: public:
explicit CharConverter(basic_arg<Context> &arg) : arg_(arg) {} explicit char_converter(basic_arg<Context> &arg) : arg_(arg) {}
template <typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value>::type typename std::enable_if<std::is_integral<T>::value>::type
...@@ -163,16 +163,16 @@ class CharConverter { ...@@ -163,16 +163,16 @@ class CharConverter {
// Checks if an argument is a valid printf width specifier and sets // Checks if an argument is a valid printf width specifier and sets
// left alignment if it is negative. // left alignment if it is negative.
template <typename Char> template <typename Char>
class PrintfWidthHandler { class printf_width_handler: public function<unsigned> {
private: private:
typedef basic_format_specs<Char> format_specs; typedef basic_format_specs<Char> format_specs;
format_specs &spec_; format_specs &spec_;
FMT_DISALLOW_COPY_AND_ASSIGN(PrintfWidthHandler); FMT_DISALLOW_COPY_AND_ASSIGN(printf_width_handler);
public: public:
explicit PrintfWidthHandler(format_specs &spec) : spec_(spec) {} explicit printf_width_handler(format_specs &spec) : spec_(spec) {}
template <typename T> template <typename T>
typename std::enable_if<std::is_integral<T>::value, unsigned>::type typename std::enable_if<std::is_integral<T>::value, unsigned>::type
...@@ -213,10 +213,11 @@ class basic_printf_context; ...@@ -213,10 +213,11 @@ class basic_printf_context;
\endrst \endrst
*/ */
template <typename Range> template <typename Range>
class printf_arg_formatter : public internal::arg_formatter_base<Range> { class printf_arg_formatter:
public internal::function<void>, public internal::arg_formatter_base<Range> {
private: private:
typedef typename Range::value_type char_type; typedef typename Range::value_type char_type;
typedef decltype(std::declval<Range>().begin()) iterator; typedef decltype(internal::declval<Range>().begin()) iterator;
typedef internal::arg_formatter_base<Range> base; typedef internal::arg_formatter_base<Range> base;
typedef basic_printf_context<iterator, char_type> context_type; typedef basic_printf_context<iterator, char_type> context_type;
...@@ -417,7 +418,7 @@ unsigned basic_printf_context<OutputIt, Char, AF>::parse_header( ...@@ -417,7 +418,7 @@ unsigned basic_printf_context<OutputIt, Char, AF>::parse_header(
} else if (*it == '*') { } else if (*it == '*') {
++it; ++it;
spec.width_ = spec.width_ =
visit(internal::PrintfWidthHandler<char_type>(spec), get_arg(it)); visit(internal::printf_width_handler<char_type>(spec), get_arg(it));
} }
return arg_index; return arg_index;
} }
...@@ -453,14 +454,14 @@ void basic_printf_context<OutputIt, Char, AF>::format() { ...@@ -453,14 +454,14 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
} else if (*it == '*') { } else if (*it == '*') {
++it; ++it;
spec.precision_ = spec.precision_ =
visit(internal::PrintfPrecisionHandler(), get_arg(it)); visit(internal::printf_precision_handler(), get_arg(it));
} else { } else {
spec.precision_ = 0; spec.precision_ = 0;
} }
} }
format_arg arg = get_arg(it, arg_index); format_arg arg = get_arg(it, arg_index);
if (spec.flag(HASH_FLAG) && visit(internal::IsZeroInt(), arg)) if (spec.flag(HASH_FLAG) && visit(internal::is_zero_int(), arg))
spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG); spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
if (spec.fill_ == '0') { if (spec.fill_ == '0') {
if (arg.is_arithmetic()) if (arg.is_arithmetic())
...@@ -514,7 +515,7 @@ void basic_printf_context<OutputIt, Char, AF>::format() { ...@@ -514,7 +515,7 @@ void basic_printf_context<OutputIt, Char, AF>::format() {
break; break;
case 'c': case 'c':
// TODO: handle wchar_t // TODO: handle wchar_t
visit(internal::CharConverter<basic_printf_context>(arg), arg); visit(internal::char_converter<basic_printf_context>(arg), arg);
break; break;
} }
} }
...@@ -539,8 +540,7 @@ struct printf_context { ...@@ -539,8 +540,7 @@ struct printf_context {
std::back_insert_iterator<Buffer>, typename Buffer::value_type> type; std::back_insert_iterator<Buffer>, typename Buffer::value_type> type;
}; };
typedef basic_format_args< typedef basic_format_args<printf_context<internal::buffer>::type> printf_args;
typename printf_context<internal::buffer>::type> printf_args;
inline std::string vsprintf(string_view format, printf_args args) { inline std::string vsprintf(string_view format, printf_args args) {
memory_buffer buffer; memory_buffer buffer;
...@@ -565,7 +565,7 @@ inline std::string sprintf(string_view format_str, const Args & ... args) { ...@@ -565,7 +565,7 @@ inline std::string sprintf(string_view format_str, const Args & ... args) {
inline std::wstring vsprintf( inline std::wstring vsprintf(
wstring_view format, wstring_view format,
basic_format_args<typename printf_context<internal::wbuffer>::type> args) { basic_format_args<printf_context<internal::wbuffer>::type> args) {
wmemory_buffer buffer; wmemory_buffer buffer;
printf(buffer, format, args); printf(buffer, format, args);
return to_string(buffer); return to_string(buffer);
......
...@@ -18,7 +18,7 @@ class CustomArgFormatter : ...@@ -18,7 +18,7 @@ class CustomArgFormatter :
public fmt::arg_formatter<fmt::back_insert_range<fmt::internal::buffer>> { public fmt::arg_formatter<fmt::back_insert_range<fmt::internal::buffer>> {
public: public:
typedef fmt::back_insert_range<fmt::internal::buffer> range; typedef fmt::back_insert_range<fmt::internal::buffer> range;
typedef decltype(std::declval<range>().begin()) iterator; typedef decltype(fmt::internal::declval<range>().begin()) iterator;
typedef fmt::arg_formatter<range> base; typedef fmt::arg_formatter<range> base;
CustomArgFormatter(fmt::basic_context<iterator, char> &ctx, CustomArgFormatter(fmt::basic_context<iterator, char> &ctx,
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#undef max #undef max
template <typename T> template <typename T>
struct ValueExtractor { struct ValueExtractor: fmt::internal::function<T> {
T operator()(T value) { T operator()(T value) {
return value; return value;
} }
...@@ -59,7 +59,7 @@ struct ValueExtractor { ...@@ -59,7 +59,7 @@ struct ValueExtractor {
TEST(FormatTest, ArgConverter) { TEST(FormatTest, ArgConverter) {
long long value = std::numeric_limits<long long>::max(); long long value = std::numeric_limits<long long>::max();
auto arg = fmt::internal::make_arg<fmt::context>(value); auto arg = fmt::internal::make_arg<fmt::context>(value);
visit(fmt::internal::ArgConverter<long long, fmt::context>(arg, 'd'), arg); visit(fmt::internal::arg_converter<long long, fmt::context>(arg, 'd'), arg);
EXPECT_EQ(value, visit(ValueExtractor<long long>(), arg)); EXPECT_EQ(value, visit(ValueExtractor<long long>(), arg));
} }
......
...@@ -1205,7 +1205,9 @@ TEST(FormatterTest, FormatPointer) { ...@@ -1205,7 +1205,9 @@ TEST(FormatterTest, FormatPointer) {
EXPECT_EQ("0x" + std::string(sizeof(void*) * CHAR_BIT / 4, 'f'), EXPECT_EQ("0x" + std::string(sizeof(void*) * CHAR_BIT / 4, 'f'),
format("{0}", reinterpret_cast<void*>(~uintptr_t()))); format("{0}", reinterpret_cast<void*>(~uintptr_t())));
EXPECT_EQ("0x1234", format("{}", fmt::ptr(reinterpret_cast<int*>(0x1234)))); EXPECT_EQ("0x1234", format("{}", fmt::ptr(reinterpret_cast<int*>(0x1234))));
EXPECT_EQ("0x0", format("{}", nullptr)); #if FMT_USE_NULLPTR
EXPECT_EQ("0x0", format("{}", FMT_NULL));
#endif
} }
TEST(FormatterTest, FormatString) { TEST(FormatterTest, FormatString) {
...@@ -1450,7 +1452,7 @@ TEST(FormatTest, JoinArg) { ...@@ -1450,7 +1452,7 @@ TEST(FormatTest, JoinArg) {
EXPECT_EQ(L"(1, 2, 3)", format(L"({})", join(v1, v1 + 3, L", "))); EXPECT_EQ(L"(1, 2, 3)", format(L"({})", join(v1, v1 + 3, L", ")));
EXPECT_EQ("1, 2, 3", format("{0:{1}}", join(v1, v1 + 3, ", "), 1)); EXPECT_EQ("1, 2, 3", format("{0:{1}}", join(v1, v1 + 3, ", "), 1));
#if FMT_HAS_GXX_CXX11 #if FMT_USE_TRAILING_RETURN && (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 405)
EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, ", "))); EXPECT_EQ("(1, 2, 3)", format("({})", join(v1, ", ")));
EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", join(v2, ", "))); EXPECT_EQ("(+01.20, +03.40)", format("({:+06.2f})", join(v2, ", ")));
#endif #endif
...@@ -1551,7 +1553,8 @@ TEST(FormatTest, FixedEnum) { ...@@ -1551,7 +1553,8 @@ TEST(FormatTest, FixedEnum) {
typedef fmt::back_insert_range<fmt::internal::buffer> buffer_range; typedef fmt::back_insert_range<fmt::internal::buffer> buffer_range;
class mock_arg_formatter : class mock_arg_formatter:
public fmt::internal::function<void>,
public fmt::internal::arg_formatter_base<buffer_range> { public fmt::internal::arg_formatter_base<buffer_range> {
private: private:
MOCK_METHOD1(call, void (int value)); MOCK_METHOD1(call, void (int value));
...@@ -1602,8 +1605,8 @@ template <> ...@@ -1602,8 +1605,8 @@ template <>
struct formatter<variant> : dynamic_formatter<> { struct formatter<variant> : dynamic_formatter<> {
auto format(variant value, context& ctx) -> decltype(ctx.begin()) { auto format(variant value, context& ctx) -> decltype(ctx.begin()) {
if (value.type == variant::INT) if (value.type == variant::INT)
return dynamic_formatter::format(42, ctx); return dynamic_formatter<>::format(42, ctx);
return dynamic_formatter::format("foo", ctx); return dynamic_formatter<>::format("foo", ctx);
} }
}; };
} }
......
...@@ -478,12 +478,12 @@ bool operator==(custom_value<Char> lhs, custom_value<Char> rhs) { ...@@ -478,12 +478,12 @@ bool operator==(custom_value<Char> lhs, custom_value<Char> rhs) {
} }
} }
template <typename T> // Use a unique result type to make sure that there are no undesirable
struct MockVisitor { // conversions.
// Use a unique result type to make sure that there are no undesirable struct Result {};
// conversions.
struct Result {};
template <typename T>
struct MockVisitor: fmt::internal::function<Result> {
MockVisitor() { MockVisitor() {
ON_CALL(*this, visit(_)).WillByDefault(Return(Result())); ON_CALL(*this, visit(_)).WillByDefault(Return(Result()));
} }
...@@ -529,8 +529,9 @@ VISIT_TYPE(float, double); ...@@ -529,8 +529,9 @@ VISIT_TYPE(float, double);
fmt::visit(visitor, make_arg<fmt::basic_context<iterator, Char>>(value)); \ fmt::visit(visitor, make_arg<fmt::basic_context<iterator, Char>>(value)); \
} }
#define CHECK_ARG(value) { \ #define CHECK_ARG(value, typename_) { \
typename VisitType<decltype(value)>::Type expected = value; \ typedef decltype(value) value_type; \
typename_ VisitType<value_type>::Type expected = value; \
CHECK_ARG_(char, expected, value) \ CHECK_ARG_(char, expected, value) \
CHECK_ARG_(wchar_t, expected, value) \ CHECK_ARG_(wchar_t, expected, value) \
} }
...@@ -556,9 +557,9 @@ typename std::enable_if<std::is_floating_point<T>::value, T>::type ...@@ -556,9 +557,9 @@ typename std::enable_if<std::is_floating_point<T>::value, T>::type
} }
TYPED_TEST(NumericArgTest, MakeAndVisit) { TYPED_TEST(NumericArgTest, MakeAndVisit) {
CHECK_ARG(test_value<TypeParam>()); CHECK_ARG(test_value<TypeParam>(), typename);
CHECK_ARG(std::numeric_limits<TypeParam>::min()); CHECK_ARG(std::numeric_limits<TypeParam>::min(), typename);
CHECK_ARG(std::numeric_limits<TypeParam>::max()); CHECK_ARG(std::numeric_limits<TypeParam>::max(), typename);
} }
TEST(UtilTest, CharArg) { TEST(UtilTest, CharArg) {
...@@ -594,22 +595,25 @@ TEST(UtilTest, PointerArg) { ...@@ -594,22 +595,25 @@ TEST(UtilTest, PointerArg) {
const void *cp = 0; const void *cp = 0;
CHECK_ARG_(char, cp, p); CHECK_ARG_(char, cp, p);
CHECK_ARG_(wchar_t, cp, p); CHECK_ARG_(wchar_t, cp, p);
CHECK_ARG(cp); CHECK_ARG(cp, );
} }
TEST(UtilTest, CustomArg) { struct check_custom {
::Test test; Result operator()(fmt::basic_arg<fmt::context>::handle h) const {
typedef typename fmt::basic_arg<fmt::context>::handle handle;
typedef MockVisitor<handle> visitor;
testing::StrictMock<visitor> v;
EXPECT_CALL(v, visit(_)).WillOnce(testing::Invoke([&](handle h) {
fmt::memory_buffer buffer; fmt::memory_buffer buffer;
fmt::internal::basic_buffer<char> &base = buffer; fmt::internal::basic_buffer<char> &base = buffer;
fmt::context ctx(std::back_inserter(base), "", fmt::format_args()); fmt::context ctx(std::back_inserter(base), "", fmt::format_args());
h.format(ctx); h.format(ctx);
EXPECT_EQ("test", std::string(buffer.data(), buffer.size())); EXPECT_EQ("test", std::string(buffer.data(), buffer.size()));
return visitor::Result(); return Result();
})); }
};
TEST(UtilTest, CustomArg) {
::Test test;
typedef MockVisitor<fmt::basic_arg<fmt::context>::handle> visitor;
testing::StrictMock<visitor> v;
EXPECT_CALL(v, visit(_)).WillOnce(testing::Invoke(check_custom()));
fmt::visit(v, make_arg<fmt::context>(test)); fmt::visit(v, make_arg<fmt::context>(test));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment