+#if wxDEBUG_LEVEL
+ // Check that the format specifier for index-th argument in 'fmt' has
+ // the correct type (one of wxFormatString::Arg_XXX or-combination in
+ // 'expected_mask').
+ #define wxASSERT_ARG_TYPE(fmt, index, expected_mask) \
+ do \
+ { \
+ if ( !fmt ) \
+ break; \
+ const int argtype = fmt->GetArgumentType(index); \
+ wxASSERT_MSG( (argtype & (expected_mask)) == argtype, \
+ "format specifier doesn't match argument type" ); \
+ } while ( wxFalse )
+#else
+ #define wxASSERT_ARG_TYPE(fmt, index, expected_mask)
+#endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL
+
+
+#if defined(HAVE_TYPE_TRAITS) || defined(HAVE_TR1_TYPE_TRAITS)
+
+// Note: this type is misnamed, so that the error message is easier to
+// understand (no error happens for enums, because the IsEnum=true case is
+// specialized).
+template<bool IsEnum>
+struct wxFormatStringSpecifierNonPodType {};
+
+template<>
+struct wxFormatStringSpecifierNonPodType<true>
+{
+ enum { value = wxFormatString::Arg_Int };
+};
+
+template<typename T>
+struct wxFormatStringSpecifier
+{
+#ifdef HAVE_TYPE_TRAITS
+ typedef std::is_enum<T> is_enum;
+#elif defined HAVE_TR1_TYPE_TRAITS
+ typedef std::tr1::is_enum<T> is_enum;
+#endif
+ enum { value = wxFormatStringSpecifierNonPodType<is_enum::value>::value };
+};
+
+#else // !HAVE_(TR1_)TYPE_TRAITS
+
+template<typename T>
+struct wxFormatStringSpecifier
+{
+ // We can't detect enums without is_enum, so the only thing we can
+ // do is to accept unknown types. However, the only acceptable unknown
+ // types still are enums, which are promoted to ints, so return Arg_Int
+ // here. This will at least catch passing of non-POD types through ... at
+ // runtime.
+ //
+ // Furthermore, if the compiler doesn't have partial template
+ // specialization, we didn't cover pointers either.
+#ifdef HAVE_PARTIAL_SPECIALIZATION
+ enum { value = wxFormatString::Arg_Int };
+#else
+ enum { value = wxFormatString::Arg_Int | wxFormatString::Arg_Pointer };
+#endif
+};
+
+#endif // HAVE_TR1_TYPE_TRAITS/!HAVE_TR1_TYPE_TRAITS
+
+
+#ifdef HAVE_PARTIAL_SPECIALIZATION
+template<typename T>
+struct wxFormatStringSpecifier<T*>
+{
+ enum { value = wxFormatString::Arg_Pointer };
+};
+
+template<typename T>
+struct wxFormatStringSpecifier<const T*>
+{
+ enum { value = wxFormatString::Arg_Pointer };
+};
+#endif // !HAVE_PARTIAL_SPECIALIZATION
+
+
+#define wxFORMAT_STRING_SPECIFIER(T, arg) \
+ template<> struct wxFormatStringSpecifier<T> \
+ { \
+ enum { value = arg }; \
+ };
+
+wxFORMAT_STRING_SPECIFIER(bool, wxFormatString::Arg_Int)
+wxFORMAT_STRING_SPECIFIER(int, wxFormatString::Arg_Int)
+wxFORMAT_STRING_SPECIFIER(unsigned int, wxFormatString::Arg_Int)
+wxFORMAT_STRING_SPECIFIER(short int, wxFormatString::Arg_Int)
+wxFORMAT_STRING_SPECIFIER(short unsigned int, wxFormatString::Arg_Int)
+wxFORMAT_STRING_SPECIFIER(long int, wxFormatString::Arg_LongInt)
+wxFORMAT_STRING_SPECIFIER(long unsigned int, wxFormatString::Arg_LongInt)
+#ifdef wxLongLong_t
+wxFORMAT_STRING_SPECIFIER(wxLongLong_t, wxFormatString::Arg_LongLongInt)
+wxFORMAT_STRING_SPECIFIER(wxULongLong_t, wxFormatString::Arg_LongLongInt)
+#endif
+wxFORMAT_STRING_SPECIFIER(float, wxFormatString::Arg_Double)
+wxFORMAT_STRING_SPECIFIER(double, wxFormatString::Arg_Double)
+wxFORMAT_STRING_SPECIFIER(long double, wxFormatString::Arg_LongDouble)
+
+#if wxWCHAR_T_IS_REAL_TYPE
+wxFORMAT_STRING_SPECIFIER(wchar_t, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
+#endif
+
+#if !wxUSE_UNICODE
+wxFORMAT_STRING_SPECIFIER(char, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
+wxFORMAT_STRING_SPECIFIER(signed char, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
+wxFORMAT_STRING_SPECIFIER(unsigned char, wxFormatString::Arg_Char | wxFormatString::Arg_Int)
+#endif
+
+wxFORMAT_STRING_SPECIFIER(char*, wxFormatString::Arg_String)
+wxFORMAT_STRING_SPECIFIER(unsigned char*, wxFormatString::Arg_String)
+wxFORMAT_STRING_SPECIFIER(signed char*, wxFormatString::Arg_String)
+wxFORMAT_STRING_SPECIFIER(const char*, wxFormatString::Arg_String)
+wxFORMAT_STRING_SPECIFIER(const unsigned char*, wxFormatString::Arg_String)
+wxFORMAT_STRING_SPECIFIER(const signed char*, wxFormatString::Arg_String)
+wxFORMAT_STRING_SPECIFIER(wchar_t*, wxFormatString::Arg_String)
+wxFORMAT_STRING_SPECIFIER(const wchar_t*, wxFormatString::Arg_String)
+
+wxFORMAT_STRING_SPECIFIER(int*, wxFormatString::Arg_IntPtr | wxFormatString::Arg_Pointer)
+wxFORMAT_STRING_SPECIFIER(short int*, wxFormatString::Arg_ShortIntPtr | wxFormatString::Arg_Pointer)
+wxFORMAT_STRING_SPECIFIER(long int*, wxFormatString::Arg_LongIntPtr | wxFormatString::Arg_Pointer)
+
+#undef wxFORMAT_STRING_SPECIFIER
+
+