Added wxIsPod<>. Use it in wxAny instead of wxIsMovable<>.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64589 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Jaakko Salli 2010-06-14 15:12:37 +00:00
parent 97b8472b54
commit 109e2ca434
24 changed files with 236 additions and 69 deletions

View File

@ -471,6 +471,7 @@ ALL_BASE_HEADERS = \
wx/meta/if.h \
wx/meta/int2type.h \
wx/meta/movable.h \
wx/meta/pod.h \
wx/fswatcher.h \
wx/generic/fswatcher.h \
$(BASE_PLATFORM_HDR) \
@ -639,6 +640,7 @@ ALL_PORTS_BASE_HEADERS = \
wx/meta/if.h \
wx/meta/int2type.h \
wx/meta/movable.h \
wx/meta/pod.h \
wx/fswatcher.h \
wx/generic/fswatcher.h \
wx/unix/app.h \

View File

@ -556,6 +556,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
wx/meta/if.h
wx/meta/int2type.h
wx/meta/movable.h
wx/meta/pod.h
wx/fswatcher.h
wx/generic/fswatcher.h
</set>

View File

@ -1423,6 +1423,10 @@ SOURCE=..\..\include\wx\platinfo.h
# End Source File
# Begin Source File
SOURCE=..\..\include\wx\meta\pod.h
# End Source File
# Begin Source File
SOURCE=..\..\include\wx\power.h
# End Source File
# Begin Source File

View File

@ -1499,6 +1499,9 @@
<File
RelativePath="..\..\include\wx\platinfo.h">
</File>
<File
RelativePath="..\..\include\wx\meta\pod.h">
</File>
<File
RelativePath="..\..\include\wx\power.h">
</File>

View File

@ -2017,6 +2017,10 @@
RelativePath="..\..\include\wx\platinfo.h"
>
</File>
<File
RelativePath="..\..\include\wx\meta\pod.h"
>
</File>
<File
RelativePath="..\..\include\wx\power.h"
>

View File

@ -2013,6 +2013,10 @@
RelativePath="..\..\include\wx\platinfo.h"
>
</File>
<File
RelativePath="..\..\include\wx\meta\pod.h"
>
</File>
<File
RelativePath="..\..\include\wx\power.h"
>

View File

@ -17,7 +17,7 @@
#if wxUSE_ANY
#include "wx/string.h"
#include "wx/meta/movable.h"
#include "wx/meta/pod.h"
#include "wx/meta/if.h"
#include "wx/typeinfo.h"
@ -193,7 +193,7 @@ namespace wxPrivate
{
template<typename T>
class wxAnyValueTypeOpsMovable
class wxAnyValueTypeOpsPOD
{
public:
static void DeleteValue(wxAnyValueBuffer& buf)
@ -270,9 +270,9 @@ public:
template<typename T>
class wxAnyValueTypeImplBase : public wxAnyValueType
{
typedef typename wxIf< wxIsMovable<T>::value &&
typedef typename wxIf< wxIsPod<T>::value &&
sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE,
wxPrivate::wxAnyValueTypeOpsMovable<T>,
wxPrivate::wxAnyValueTypeOpsPOD<T>,
wxPrivate::wxAnyValueTypeOpsGeneric<T> >::value
Ops;

View File

@ -11,20 +11,9 @@
#ifndef _WX_META_MOVABLE_H_
#define _WX_META_MOVABLE_H_
#include "wx/defs.h"
#include "wx/meta/pod.h"
#include "wx/string.h" // for wxIsMovable<wxString> specialization
// This macro declares something called "value" inside a class declaration.
//
// It has to be used because VC6 doesn't handle initialization of the static
// variables in the class declaration itself while BCC5.82 doesn't understand
// enums (it compiles the template fine but can't use it later)
#if defined(__VISUALC__) && !wxCHECK_VISUALC_VERSION(7)
#define wxDEFINE_TEMPLATE_BOOL_VALUE(val) enum { value = val }
#else
#define wxDEFINE_TEMPLATE_BOOL_VALUE(val) static const bool value = val
#endif
// Helper to decide if an object of type T is "movable", i.e. if it can be
// copied to another memory location using memmove() or realloc() C functions.
// C++ only gurantees that POD types (including primitive types) are
@ -32,7 +21,7 @@
template<typename T>
struct wxIsMovable
{
wxDEFINE_TEMPLATE_BOOL_VALUE(false);
wxDEFINE_TEMPLATE_BOOL_VALUE(wxIsPod<T>::value);
};
// Macro to add wxIsMovable<T> specialization for given type that marks it
@ -43,46 +32,6 @@ struct wxIsMovable
wxDEFINE_TEMPLATE_BOOL_VALUE(true); \
};
WX_DECLARE_TYPE_MOVABLE(bool)
WX_DECLARE_TYPE_MOVABLE(unsigned char)
WX_DECLARE_TYPE_MOVABLE(signed char)
WX_DECLARE_TYPE_MOVABLE(unsigned int)
WX_DECLARE_TYPE_MOVABLE(signed int)
WX_DECLARE_TYPE_MOVABLE(unsigned short int)
WX_DECLARE_TYPE_MOVABLE(signed short int)
WX_DECLARE_TYPE_MOVABLE(signed long int)
WX_DECLARE_TYPE_MOVABLE(unsigned long int)
WX_DECLARE_TYPE_MOVABLE(float)
WX_DECLARE_TYPE_MOVABLE(double)
WX_DECLARE_TYPE_MOVABLE(long double)
#if wxWCHAR_T_IS_REAL_TYPE
WX_DECLARE_TYPE_MOVABLE(wchar_t)
#endif
#ifdef wxLongLong_t
WX_DECLARE_TYPE_MOVABLE(wxLongLong_t)
WX_DECLARE_TYPE_MOVABLE(wxULongLong_t)
#endif
// Visual C++ 6.0 can't compile partial template specializations and as this is
// only an optimization, we can live with pointers not being recognized as
// movable types under VC6
#if !defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7)
// pointers are movable:
template<typename T>
struct wxIsMovable<T*>
{
static const bool value = true;
};
template<typename T>
struct wxIsMovable<const T*>
{
static const bool value = true;
};
#endif // !VC++ < 7
// Our implementation of wxString is written in such way that it's safe to move
// it around (unless position cache is used which unfortunately breaks this).
// OTOH, we don't know anything about std::string.

88
include/wx/meta/pod.h Normal file
View File

@ -0,0 +1,88 @@
/////////////////////////////////////////////////////////////////////////////
// Name: wx/meta/pod.h
// Purpose: Test if a type is POD
// Author: Vaclav Slavik, Jaakko Salli
// Created: 2010-06-14
// RCS-ID: $Id$
// Copyright: (c) wxWidgets team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_META_POD_H_
#define _WX_META_POD_H_
#include "wx/defs.h"
//
// TODO: Use TR1 is_pod<> implementation where available. VC9 SP1 has it
// in tr1 namespace, VC10 has it in std namespace. GCC 4.2 has it in
// <tr1/type_traits>, while GCC 4.3 and later have it in <type_traits>.
//
// This macro declares something called "value" inside a class declaration.
//
// It has to be used because VC6 doesn't handle initialization of the static
// variables in the class declaration itself while BCC5.82 doesn't understand
// enums (it compiles the template fine but can't use it later)
#if defined(__VISUALC__) && !wxCHECK_VISUALC_VERSION(7)
#define wxDEFINE_TEMPLATE_BOOL_VALUE(val) enum { value = val }
#else
#define wxDEFINE_TEMPLATE_BOOL_VALUE(val) static const bool value = val
#endif
// Helper to decide if an object of type T is POD (Plain Old Data)
template<typename T>
struct wxIsPod
{
wxDEFINE_TEMPLATE_BOOL_VALUE(false);
};
// Macro to add wxIsPod<T> specialization for given type that marks it
// as Plain Old Data:
#define WX_DECLARE_TYPE_POD(type) \
template<> struct wxIsPod<type> \
{ \
wxDEFINE_TEMPLATE_BOOL_VALUE(true); \
};
WX_DECLARE_TYPE_POD(bool)
WX_DECLARE_TYPE_POD(unsigned char)
WX_DECLARE_TYPE_POD(signed char)
WX_DECLARE_TYPE_POD(unsigned int)
WX_DECLARE_TYPE_POD(signed int)
WX_DECLARE_TYPE_POD(unsigned short int)
WX_DECLARE_TYPE_POD(signed short int)
WX_DECLARE_TYPE_POD(signed long int)
WX_DECLARE_TYPE_POD(unsigned long int)
WX_DECLARE_TYPE_POD(float)
WX_DECLARE_TYPE_POD(double)
WX_DECLARE_TYPE_POD(long double)
#if wxWCHAR_T_IS_REAL_TYPE
WX_DECLARE_TYPE_POD(wchar_t)
#endif
#ifdef wxLongLong_t
WX_DECLARE_TYPE_POD(wxLongLong_t)
WX_DECLARE_TYPE_POD(wxULongLong_t)
#endif
// Visual C++ 6.0 can't compile partial template specializations and as this is
// only an optimization, we can live with pointers not being recognized as
// POD types under VC6
#if !defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7)
// pointers are Plain Old Data:
template<typename T>
struct wxIsPod<T*>
{
static const bool value = true;
};
template<typename T>
struct wxIsPod<const T*>
{
static const bool value = true;
};
#endif // !VC++ < 7
#endif // _WX_META_POD_H_

View File

@ -45,23 +45,27 @@
When compared to wxVariant, there are various internal implementation
differences as well. For instance, wxAny only allocates separate data
object in heap for large (ie. size in bytes more than
WX_ANY_VALUE_BUFFER_SIZE) or 'non-movable' data types. Pointers, integers,
bools etc. are fitted in the wxAny's own buffer without need for any extra
allocation. Use following code to declare your own data type as 'movable':
object in heap for large (i.e. size in bytes more than
WX_ANY_VALUE_BUFFER_SIZE) or non-POD (Plain Old Data) data types.
Pointers, integers, bools etc. are fitted in the wxAny's internal buffer
without need for any extra allocation. It is possible that wxAny cannot
automatically determine if your own data structure is considered a
POD or not, so you may need to declare it as such explicitly, using
code like this:
@code
#include "wx/meta/movable.h"
WX_DECLARE_TYPE_MOVABLE(MyClass)
#include "wx/meta/pod.h"
WX_DECLARE_TYPE_POD(MyPodStruct)
@endcode
However, you must be aware that 'movable' means such data that can be
copied with memcpy() without corrupting program integrity. For instance,
movable objects usually cannot contain pointers or references to other
data. wxRect, wxPoint, and wxSize are good examples of movable classes.
Be extra careful what you declare as Plain Old Data. It must be such data
that can be copied with memcpy() without corrupting program integrity. For
instance, POD structures usually cannot contain pointers or references to
other data. wxRect, wxPoint, and wxSize are good examples of POD
classes.
Note that pointers to any and all classes are already automatically
declared as movable data.
Note that pointers to any and all types are already automatically
declared as Plain Old Data.
@library{wxbase}
@category{data}

View File

@ -86,6 +86,7 @@ TEST_OBJECTS = \
test_mbconvtest.o \
test_dynamiclib.o \
test_environ.o \
test_metatest.o \
test_misctests.o \
test_module.o \
test_pathlist.o \
@ -460,6 +461,9 @@ test_dynamiclib.o: $(srcdir)/misc/dynamiclib.cpp $(TEST_ODEP)
test_environ.o: $(srcdir)/misc/environ.cpp $(TEST_ODEP)
$(CXXC) -c -o $@ $(TEST_CXXFLAGS) $(srcdir)/misc/environ.cpp
test_metatest.o: $(srcdir)/misc/metatest.cpp $(TEST_ODEP)
$(CXXC) -c -o $@ $(TEST_CXXFLAGS) $(srcdir)/misc/metatest.cpp
test_misctests.o: $(srcdir)/misc/misctests.cpp $(TEST_ODEP)
$(CXXC) -c -o $@ $(TEST_CXXFLAGS) $(srcdir)/misc/misctests.cpp

View File

@ -70,6 +70,7 @@ TEST_OBJECTS = \
$(OBJS)\test_mbconvtest.obj \
$(OBJS)\test_dynamiclib.obj \
$(OBJS)\test_environ.obj \
$(OBJS)\test_metatest.obj \
$(OBJS)\test_misctests.obj \
$(OBJS)\test_module.obj \
$(OBJS)\test_pathlist.obj \
@ -502,6 +503,9 @@ $(OBJS)\test_dynamiclib.obj: .\misc\dynamiclib.cpp
$(OBJS)\test_environ.obj: .\misc\environ.cpp
$(CXX) -q -c -P -o$@ $(TEST_CXXFLAGS) .\misc\environ.cpp
$(OBJS)\test_metatest.obj: .\misc\metatest.cpp
$(CXX) -q -c -P -o$@ $(TEST_CXXFLAGS) .\misc\metatest.cpp
$(OBJS)\test_misctests.obj: .\misc\misctests.cpp
$(CXX) -q -c -P -o$@ $(TEST_CXXFLAGS) .\misc\misctests.cpp

View File

@ -62,6 +62,7 @@ TEST_OBJECTS = \
$(OBJS)\test_mbconvtest.o \
$(OBJS)\test_dynamiclib.o \
$(OBJS)\test_environ.o \
$(OBJS)\test_metatest.o \
$(OBJS)\test_misctests.o \
$(OBJS)\test_module.o \
$(OBJS)\test_pathlist.o \
@ -483,6 +484,9 @@ $(OBJS)\test_dynamiclib.o: ./misc/dynamiclib.cpp
$(OBJS)\test_environ.o: ./misc/environ.cpp
$(CXX) -c -o $@ $(TEST_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\test_metatest.o: ./misc/metatest.cpp
$(CXX) -c -o $@ $(TEST_CXXFLAGS) $(CPPDEPS) $<
$(OBJS)\test_misctests.o: ./misc/misctests.cpp
$(CXX) -c -o $@ $(TEST_CXXFLAGS) $(CPPDEPS) $<

View File

@ -64,6 +64,7 @@ TEST_OBJECTS = \
$(OBJS)\test_mbconvtest.obj \
$(OBJS)\test_dynamiclib.obj \
$(OBJS)\test_environ.obj \
$(OBJS)\test_metatest.obj \
$(OBJS)\test_misctests.obj \
$(OBJS)\test_module.obj \
$(OBJS)\test_pathlist.obj \
@ -628,6 +629,9 @@ $(OBJS)\test_dynamiclib.obj: .\misc\dynamiclib.cpp
$(OBJS)\test_environ.obj: .\misc\environ.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_CXXFLAGS) .\misc\environ.cpp
$(OBJS)\test_metatest.obj: .\misc\metatest.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_CXXFLAGS) .\misc\metatest.cpp
$(OBJS)\test_misctests.obj: .\misc\misctests.cpp
$(CXX) /c /nologo /TP /Fo$@ $(TEST_CXXFLAGS) .\misc\misctests.cpp

View File

@ -300,6 +300,7 @@ TEST_OBJECTS = &
$(OBJS)\test_mbconvtest.obj &
$(OBJS)\test_dynamiclib.obj &
$(OBJS)\test_environ.obj &
$(OBJS)\test_metatest.obj &
$(OBJS)\test_misctests.obj &
$(OBJS)\test_module.obj &
$(OBJS)\test_pathlist.obj &
@ -540,6 +541,9 @@ $(OBJS)\test_dynamiclib.obj : .AUTODEPEND .\misc\dynamiclib.cpp
$(OBJS)\test_environ.obj : .AUTODEPEND .\misc\environ.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(TEST_CXXFLAGS) $<
$(OBJS)\test_metatest.obj : .AUTODEPEND .\misc\metatest.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(TEST_CXXFLAGS) $<
$(OBJS)\test_misctests.obj : .AUTODEPEND .\misc\misctests.cpp
$(CXX) -bt=nt -zq -fo=$^@ $(TEST_CXXFLAGS) $<

69
tests/misc/metatest.cpp Normal file
View File

@ -0,0 +1,69 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/misc/metatest.cpp
// Purpose: Test template meta-programming constructs
// Author: Jaakko Salli
// RCS-ID: $Id$
// Copyright: (c) the wxWidgets team
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#ifdef __BORLANDC__
# pragma hdrstop
#endif
#include "wx/object.h"
#include "wx/meta/pod.h"
#include "wx/meta/movable.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class MetaProgrammingTestCase : public CppUnit::TestCase
{
public:
MetaProgrammingTestCase() { }
private:
CPPUNIT_TEST_SUITE( MetaProgrammingTestCase );
CPPUNIT_TEST( IsPod );
CPPUNIT_TEST( IsMovable );
CPPUNIT_TEST_SUITE_END();
void IsPod();
void IsMovable();
DECLARE_NO_COPY_CLASS(MetaProgrammingTestCase)
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( MetaProgrammingTestCase );
// also include in it's own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MetaProgrammingTestCase,
"MetaProgrammingTestCase" );
void MetaProgrammingTestCase::IsPod()
{
CPPUNIT_ASSERT(wxIsPod<bool>::value);
CPPUNIT_ASSERT(wxIsPod<signed int>::value);
CPPUNIT_ASSERT(wxIsPod<double>::value);
#if !defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7)
CPPUNIT_ASSERT(wxIsPod<wxObject*>::value);
#endif
CPPUNIT_ASSERT(!wxIsPod<wxObject>::value);
}
void MetaProgrammingTestCase::IsMovable()
{
CPPUNIT_ASSERT(wxIsMovable<bool>::value);
CPPUNIT_ASSERT(wxIsMovable<signed int>::value);
CPPUNIT_ASSERT(wxIsMovable<double>::value);
#if !defined(__VISUALC__) || wxCHECK_VISUALC_VERSION(7)
CPPUNIT_ASSERT(wxIsMovable<wxObject*>::value);
#endif
CPPUNIT_ASSERT(!wxIsMovable<wxObject>::value);
}

View File

@ -61,6 +61,7 @@
mbconv/mbconvtest.cpp
misc/dynamiclib.cpp
misc/environ.cpp
misc/metatest.cpp
misc/misctests.cpp
misc/module.cpp
misc/pathlist.cpp

View File

@ -405,6 +405,10 @@ SOURCE=.\streams\memstream.cpp
# End Source File
# Begin Source File
SOURCE=.\misc\metatest.cpp
# End Source File
# Begin Source File
SOURCE=.\thread\misc.cpp
# End Source File
# Begin Source File

View File

@ -739,6 +739,9 @@
<File
RelativePath=".\streams\memstream.cpp">
</File>
<File
RelativePath=".\misc\metatest.cpp">
</File>
<File
RelativePath=".\thread\misc.cpp">
</File>

View File

@ -1059,6 +1059,10 @@
RelativePath=".\streams\memstream.cpp"
>
</File>
<File
RelativePath=".\misc\metatest.cpp"
>
</File>
<File
RelativePath=".\thread\misc.cpp"
>

View File

@ -1031,6 +1031,10 @@
RelativePath=".\streams\memstream.cpp"
>
</File>
<File
RelativePath=".\misc\metatest.cpp"
>
</File>
<File
RelativePath=".\thread\misc.cpp"
>

View File

@ -353,6 +353,7 @@ wx/meta/convertible.h
wx/meta/if.h
wx/meta/int2type.h
wx/meta/movable.h
wx/meta/pod.h
wx/fswatcher.h
wx/generic/fswatcher.h
wx/unix/app.h

View File

@ -258,6 +258,7 @@ wx/meta/convertible.h
wx/meta/if.h
wx/meta/int2type.h
wx/meta/movable.h
wx/meta/pod.h
wx/fswatcher.h
wx/generic/fswatcher.h
wx/unix/app.h

View File

@ -282,6 +282,7 @@ wx/meta/convertible.h
wx/meta/if.h
wx/meta/int2type.h
wx/meta/movable.h
wx/meta/pod.h
wx/fswatcher.h
wx/generic/fswatcher.h
wx/unix/app.h