Reputation: 7318
I wrote a application in MFC with C++. I need to write a class which can save all the data loaded from the database, These data might contain every kind of data type, such as int, string, byte, boolean, datetime and so on. We might filter, exchange columns, or sort on these data. For example:
int int string bool double float .... string
0 1 "a" false 3.14 3.0 "b"
1 2 "5" true 3.22 4 "c"
Note: We didn't use SQL to sort or filter, since we have our consideration.
We have wrote the following class, could someone have better suggestion, please write a sample class for use, thanks in advance!
#ifndef __LIST_DATA_MODEL_H__
#define __LIST_DATA_MODEL_H__
#include <vector>
using std::vector;
///implement a pure virtual base class; parameters of function is a void pointer,
class FieldType
{
public:
enum {
TypeChar = 0,
TypeString = 1,
TypeBool = 2,
TypeShort = 3,
TypeUShort = 4,
TypeInt = 5,
TypeUInt = 6,
TypeLong = 7,
TypeULong = 8,
TypeLongLong = 9,
TypeULongLong = 10,
TypeFloat = 11,
TypeDouble = 12
};
};
template <typename _ValueType, typename _SyncType>
class Column
{
protected:
CString m_szFieldName;
vector<_ValueType> m_vValues;
public:
Column();
Column(CString szFieldName);
Column(const Column& other);
virtual ~Column();
public:
virtual BOOL LoadData(...);
public:
///This function will call LoadData function to re-load data,
///if subclass this class, please implement your LoadData function
///if you want additional operation when load data.
CALLBACK BOOL Update();
public:
const int ValueCount() const;
const CString& FieldName() const;
const _ValueType& ValueAt(int iPos) const;
///Before you call LoadData function or Update Function, the values will not updated;
void SetFieldName(const CString& szFieldName);
void SetValue(const _ValueType& val, int iPos);
};
template<class _Type>
class DataItem
{
protected:
_Type _value;
public:
DataItem();
DataItem(const DataItem& other)
{
_value = other._value;
};
DataItem(const _Type& val)
{
_value = val;
};
virtual ~DataItem()
{
};
public:
const _Type& GetValue()
{
return _value;
};
void SetValue(const _Type& value)
{
_value = value;
};
void ResetValue()
{
_value = _Type();
};
public:
bool operator ==(DataItem& right)
{
return _value == right._value;
};
bool operator <(const DataItem& right)
{
return _value < right._value;
};
const DataItem& operator =(const DataItem& right)
{
if(this == &right)
return *this;
_value = right._value;
return *this;
};
virtual DataItem* Clone()
{
return new DataItem(*this);
};
};
typedef DataItem<int> IntItem;
typedef DataItem<float> FloatItem;
typedef DataItem<double> DoubleItem;
typedef DataItem<CString> StringItem;
typedef DataItem<bool> BoolItem;
typedef DataItem<TCHAR> CharItem;
typedef DataItem<char> ByteItem;
typedef DataItem<CString> CStringItem;
#endif
Upvotes: 0
Views: 4147
Reputation: 7180
I am wondering if you are emulating the DB behavior, then does it make sense to store the data in containers of 'type'? Since the data will be accessed via column-names, you need to have containers that store data-values for each column and have column-name to column-type mapping. Anyway if you want to store data along with its type then consider the following approach using 'stringization of enums':-
std::vector<string>
.On how to create stringized enums and use them follow link here and here. The Macro's approach. Or you can use a templatized approcah which requires use of boost something like below (only a hint :-) ).
template<typename ENUM>
class Stringifier<ENUM, typename boost::enable_if<boost::is_enum<ENUM> >::type> {
static const char * values[]; // array with the enum strings.
static std::size_t size; // Number of elements of the ENUM string arrays.
public:
/// Global static instance of the Stringifier.
static Stringifier & getInstance()
{
static Stringifier globalInstance;
return globalInstance;
}
// Returns the string representation of the ENUM value \a e as a C string.
// If string is not available an exception is thrown.
virtual void str(ENUM const & e, std::string & s) const
{
if(e >= 0 && e < int(size))
s = values[e];
else // throw exception
;
}
// Returns the ENUM value of the string representation of an ENUM value if possible,
// ENUM(0) otherwise or ENUM(size) if you like.
virtual bool value(std::string const & str, ENUM & v) const
{
std::size_t i = 0;
for(; i < size; ++i)
if(values[i] == str) break;
bool ok = (i != size);
v = ok ? ENUM(i) : ENUM(0);
return ok;
}
};
Use your enumeration as 'ENUM' in the above class.
NOTE: Stringization kills performance. So this approach is slower.
Upvotes: 2
Reputation:
A few points about your code:
_ValueType
and __LIST_DATA_MODEL_H__
are illegal in user code. Upvotes: 1
Reputation: 2287
This seems excessively complicated to me. I would implement column as a simple stl vector of the appropriate type and I'll evolve from this as needed. Try to not think too hard about this data structure or you'll create an overly complex design.
Upvotes: 0
Reputation: 7777
My first approach would be to use Boost variant or Boost any instead of creating my own.
Upvotes: 2