From f014d321473e5f5e9d7ec19d499c814d5a7510c6 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Wed, 25 Feb 2015 07:58:49 -0800 Subject: [PATCH] Improve error reporting when formatting wide into narrow strings --- format.h | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/format.h b/format.h index cb23e7b1..63c7bd72 100644 --- a/format.h +++ b/format.h @@ -738,18 +738,21 @@ struct Arg : Value { Type type; }; +template struct None {}; +// A helper class template to enable or disable overloads taking wide strings +// in MakeValue. template struct WStringHelper { - typedef None Supported; + typedef None Supported; typedef T Unsupported; }; template struct WStringHelper { typedef T Supported; - typedef None Unsupported; + typedef None Unsupported; }; // Makes a Value object from any type. @@ -766,7 +769,13 @@ class MakeValue : public Value { template MakeValue(T *value); + // The following methods are private to disallow formatting of wide + // strings into narrow strings as in fmt::format("{}", L"test"). + // To fix this, use a wide format string: fmt::format(L"{}", L"test"). + MakeValue(typename WStringHelper::Unsupported); MakeValue(typename WStringHelper::Unsupported); + MakeValue(typename WStringHelper::Unsupported); + MakeValue(typename WStringHelper::Unsupported); void set_string(StringRef str) { string.value = str.c_str(); @@ -849,17 +858,16 @@ class MakeValue : public Value { FMT_MAKE_STR_VALUE(const std::string &, STRING) FMT_MAKE_STR_VALUE(StringRef, STRING) - MakeValue(wchar_t *value) { set_string(value); } - MakeValue(typename WStringHelper::Supported value) { - set_string(value); - } - MakeValue(const std::wstring &value) { set_string(value); } - MakeValue(WStringRef value) { set_string(value); } +#define FMT_MAKE_WSTR_VALUE(Type, TYPE) \ + MakeValue(typename WStringHelper::Supported value) { \ + set_string(value); \ + } \ + static uint64_t type(Type) { return Arg::TYPE; } - static uint64_t type(wchar_t *) { return Arg::WSTRING; } - static uint64_t type(const wchar_t *) { return Arg::WSTRING; } - static uint64_t type(const std::wstring &) { return Arg::WSTRING; } - static uint64_t type(WStringRef) { return Arg::WSTRING; } + FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING) + FMT_MAKE_WSTR_VALUE(const wchar_t *, WSTRING) + FMT_MAKE_WSTR_VALUE(const std::wstring &, WSTRING) + FMT_MAKE_WSTR_VALUE(WStringRef, WSTRING) FMT_MAKE_VALUE(void *, pointer, POINTER) FMT_MAKE_VALUE(const void *, pointer, POINTER)