Make wxMin, wxMax and wxClip template functions.

Previously used macro's arguments were evaluated twice, but there were
many occurences of their use in our code that didn't account for this
and used expensive-to-evaluate arguments as if they were functions.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65920 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík 2010-10-25 09:43:00 +00:00
parent 1f4c7e791b
commit a52475807e
3 changed files with 130 additions and 4 deletions

View File

@ -554,6 +554,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
wx/zstream.h
wx/meta/convertible.h
wx/meta/if.h
wx/meta/implicitconversion.h
wx/meta/int2type.h
wx/meta/movable.h
wx/meta/pod.h

View File

@ -0,0 +1,103 @@
/////////////////////////////////////////////////////////////////////////////
// Name: wx/meta/implicitconversion.h
// Purpose: Determine resulting type from implicit conversion
// Author: Vaclav Slavik
// Created: 2010-10-22
// RCS-ID: $Id$
// Copyright: (c) 2010 Vaclav Slavik
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_META_IMPLICITCONVERSION_H_
#define _WX_META_IMPLICITCONVERSION_H_
#include "wx/defs.h"
#include "wx/meta/if.h"
// C++ hierarchy of data types is:
//
// Long double (highest)
// Double
// Float
// Unsigned long int
// Long int
// Unsigned int
// Int (lowest)
//
// Types lower in the hierarchy are converted into ones higher up if both are
// involved e.g. in arithmetic expressions.
namespace wxPrivate
{
template<typename T>
struct TypeHierarchy
{
// consider unknown types (e.g. objects, pointers) to be of highest
// level, always convert to them if they occur
enum { level = 9999 };
};
#define WX_TYPE_HIERARCHY_LEVEL(level_num, type) \
template<> struct TypeHierarchy<type> \
{ \
enum { level = level_num }; \
};
WX_TYPE_HIERARCHY_LEVEL( 1, char);
WX_TYPE_HIERARCHY_LEVEL( 2, unsigned char);
WX_TYPE_HIERARCHY_LEVEL( 3, short);
WX_TYPE_HIERARCHY_LEVEL( 4, unsigned short);
WX_TYPE_HIERARCHY_LEVEL( 5, int);
WX_TYPE_HIERARCHY_LEVEL( 6, unsigned int);
WX_TYPE_HIERARCHY_LEVEL( 7, long);
WX_TYPE_HIERARCHY_LEVEL( 8, unsigned long);
#ifdef wxLongLong_t
WX_TYPE_HIERARCHY_LEVEL( 9, wxLongLong_t);
WX_TYPE_HIERARCHY_LEVEL(10, wxULongLong_t);
#endif
WX_TYPE_HIERARCHY_LEVEL(11, float);
WX_TYPE_HIERARCHY_LEVEL(12, double);
WX_TYPE_HIERARCHY_LEVEL(13, long double);
#if wxWCHAR_T_IS_REAL_TYPE
#if SIZEOF_WCHAR_T == SIZEOF_SHORT
template<> struct TypeHierarchy<wchar_t> : public TypeHierarchy<short> {};
#elif SIZEOF_WCHAR_T == SIZEOF_INT
template<> struct TypeHierarchy<wchar_t> : public TypeHierarchy<int> {};
#elif SIZEOF_WCHAR_T == SIZEOF_LONG
template<> struct TypeHierarchy<wchar_t> : public TypeHierarchy<long> {};
#else
#error "weird wchar_t size, please update this code"
#endif
#endif
#undef WX_TYPE_HIERARCHY_LEVEL
} // namespace wxPrivate
// Helper to determine resulting type of implicit conversion in
// an expression with two arithmetic types.
template<typename T1, typename T2>
struct wxImplicitConversionType
{
typedef typename wxIf
<
// if T2 is "higher" type, convert to it
(int)wxPrivate::TypeHierarchy<T1>::level < (int)wxPrivate::TypeHierarchy<T2>::level,
T2,
// otherwise use T1
T1
>::value
value;
};
template<typename T1, typename T2, typename T3>
struct wxImplicitConversionType3 : public wxImplicitConversionType<
T1,
typename wxImplicitConversionType<T2,T3>::value>
{
};
#endif // _WX_META_IMPLICITCONVERSION_H_

View File

@ -20,6 +20,7 @@
#include "wx/list.h"
#include "wx/filefn.h"
#include "wx/hashmap.h"
#include "wx/meta/implicitconversion.h"
#if wxUSE_GUI
#include "wx/gdicmn.h"
@ -55,12 +56,33 @@ class WXDLLIMPEXP_FWD_CORE wxWindow;
class WXDLLIMPEXP_FWD_CORE wxWindowList;
// ----------------------------------------------------------------------------
// Macros
// Arithmetic functions
// ----------------------------------------------------------------------------
#define wxMax(a,b) (((a) > (b)) ? (a) : (b))
#define wxMin(a,b) (((a) < (b)) ? (a) : (b))
#define wxClip(a,b,c) (((a) < (b)) ? (b) : (((a) > (c)) ? (c) : (a)))
template<typename T1, typename T2>
inline typename wxImplicitConversionType<T1,T2>::value
wxMax(T1 a, T2 b)
{
return (a > b) ? a : b;
}
template<typename T1, typename T2>
inline typename wxImplicitConversionType<T1,T2>::value
wxMin(T1 a, T2 b)
{
return (a < b) ? a : b;
}
template<typename T1, typename T2, typename T3>
inline typename wxImplicitConversionType3<T1,T2,T3>::value
wxClip(T1 a, T2 b, T3 c)
{
return (a < b) ? b : ((a > c) ? c : a);
}
// ----------------------------------------------------------------------------
// wxMemorySize
// ----------------------------------------------------------------------------
// wxGetFreeMemory can return huge amount of memory on 32-bit platforms as well
// so to always use long long for its result type on all platforms which