Generic Type Container implemented with Templates - c++

I have a class that can generically hold any (primitive) type:
class Value
{
private:
int i_value;
unsigned int ui_value;
long l_value;
unsigned long ul_value;
short s_value;
float f_value;
double d_value;
char c_value;
bool b_value;
std::string str_value;
int type;
void setValue(int value);
void setValue(unsigned int value);
void setValue(long value);
void setValue(unsigned long value);
void setValue(short value);
void setValue(float value);
void setValue(double value);
void setValue(char value);
void setValue(bool value);
void setValue(std::string value);
public:
Value(int value);
Value(unsigned int value);
Value(long value);
Value(unsigned long value);
Value(short value);
Value(float value);
Value(double value);
Value(char value);
Value(bool value);
Value(std::string value);
Value(Value& other); //Copy Constructor
~Value();
int getType();
std::string toString(int format);
};
This is nice, because I can do something like:
Value * v1 = new Value(55);
Value * v2 = new Value(1.2);
Value * v3 = new Value("yes");
Value * v4 = new Value(true);
However, as you can see, it's pretty ugly; tons of overloading of everything to make it work. I was thinking templates could make this generic. However, as far as I can tell, you always have to specify the type, which sort of defeats the whole purpose of the class.
For example:
Value<int> * v1 = new Value<int>(55);
Value<double> * v2 = new Value<double>(1.2);
Value<string> * v3 = new Value<string>("yes");
Value<bool> * v4 = new Value<bool>(true);
If I use templates, I can no longer do something like vector<Value *> like I could before. Is this correct, or am I missing some aspect of templates that could help in this situation?

All you need is a parent base class for the template one:
class BaseValue
{
public:
virtual ~BaseValue()
{}
};
template<typename T>
class Value : public BaseValue
{
public:
Value(const T& value)
:m_value(value)
{}
void set(const T& value)
{
m_value = value;
}
const T& get()
{
return m_value;
}
virtual ~Value()
{}
private:
T m_value;
};
std::vector<BaseValue*> values;
values.push_back(new Value<int>(1)); // int
values.push_back(new Value<double>(1.0)); // double
values.push_back(new Value<char*>("asdf")); // pointer to array on stack :(
values.push_back(new Value<char>('c')); // char

First question: Use a template factory function instead of new.
Second question: Use a common base-class.
In order to be able to properly delete the objects pointed to by the pointers on the vector, you need a virtual destructor. Also, in order to do anything useful with the pointers to the base class, you need virtual methods in the base class.
Example:
class ValueBase
{
public:
virtual ~ValueBase() = default;
virtual void Print(std::ostream & os) const = 0;
};
std::ostream & operator<< (std::ostream & os, const ValueBase & value)
{
value.Print(os);
return os;
}
template<typename T> class Value : public ValueBase
{
T value;
public:
Value(const T & v) : value(v) {}
const T & Get() const;
void Set(const T & v);
void Print(std::ostream & os) const
{
os << value;
}
// ...
};
template<typename T> Value<T> * NewValue(const T & v)
{
return new Value<T>(v);
}
Now you can do
ValueBase * v1 = NewValue(55);
ValueBase * v2 = NewValue(1.2);
ValueBase * v3 = NewValue<std::string>("yes");
ValueBase * v4 = NewValue(true);
std::vector<ValueBase *> vec;
vec.push_back(v1);
vec.push_back(v2);
vec.push_back(v3);
vec.push_back(v4);
vec.push_back(NewValue(2350983444325345ll));
for (const auto & entry : vec)
{
std::cout << *entry << " ";
}
std::cout << "\n";
Note that you normally do not need the template argument of NewValue, since it will be deduced. With "yes" this does not work, since Value<T> will be instantiated with T = char [4] which would require you to use strcpy in the constructor. I find it quite nice to explicity state that a conversion is needed as above. If you prefer this implicitly, do an overload:
Value<std::string> * NewValue(const char * v)
{
return new Value<std::string>(v);
}
Make sure to delete the contents manually
for (const auto & entry : vec)
{
delete entry;
}
vec.clear();
or use std::unique_ptr instead of the bare pointer:
template<typename T> std::unique_ptr<Value<T>> UniqueValue(const T & v)
{
return std::unique_ptr<Value<T>>(new Value<T>(v));
}
std::vector<std::unique_ptr<ValueBase>> vec;
vec.push_back(NewValue(4.5));
If you extend Value and it turns out you need to do something in the destructor, you have to implement the copy constructor, assignment operator and possibly also the move constructor and move assignment operator. ("Rule of Three" or "Rule of Five".) In the above version the "Rule of Zero" still applies, since the destructor is still the same as the implicitly defined one (= default).
If you add the destructor it should be virtual. Otherwise you might get memory leaks if you delete the VirtualBase pointers.

Of course you can do templates, but you also need to do polymorphic.
class StupidAndEmpty {} // add virtual destructor if Value needs a destructor
template<class dType>
Value : StupidAndEmpty {
// do smart things with dType
}
vector<StupidAndEmpty *> notSoStupid;
Only problem is how do you use them when you get them back from vector.

Related

C++ - How to update pointer (or members) between instances of same class

I have a simple class which consists of a void pointer and an int (this is some sort of a boost::Variant educational project).
I also have a working copy constructor and a destructor.
But what grinds my gears is, how I would accomplish something like this:
Container cont1("some value"); //simple construction
Container cont2;
cont2.createLink(cont1); //this should initialize members with a reference (or something alike)
std::cout<<cont1; //yields "some value"
cont2.set(20); //setting this container should update the original container too, since I initialized with a reference (or smth alike)
std::cout<<cont1; //yields 20
This is the simplified version of the class:
class Container {
public:
Container(){}
Container(const std::string &val){var.type = STRING; var.data = new std::string(val);}
Container(int val){ /* same for int */}
Container(const Container &val){ /* do a memory copy */}
void set(int val){ /* set the value if type matches, otherwise allocate a new pointer */}
void set(const std::string &val){ /* the same as for int */}
void createLink(const Container &val){ /* somehow assign a reference or whatsoever */}
private:
typedef struct VAR {
int type = 0;
void *data = NULL; }
VAR var;
}
If I set the value of cont2 to a string (i.e. the same data type it holds at the moment), everything is fine, because the set would not allocate a new pointer and rather assign a new value.
But how do I make sure the pointer of cont1 updates if I assign a different value to cont2 and therefore have to allocate a new pointer?
Would I need something like shared_pointer?
Thanks for any insight!
EDIT:
I changed to function name to make it more clear what should happen.
There is a solution that only involves straight OO. You could create an interface for your variant type, and use double indirection to the variant instance to allow linked containers to share the same variant instance.
The reason double indirection is required is because of the way you want the set() method to automatically allocate a new variant instance if the new type doesn't match the original type. If we simply shared a pointer to the variant from both containers, then after set() creates a new variant instance, each container would be referring to different instances again.
To get around that, we can use a pointer to a pointer to a variant in the container instead.
Here is a possible way to define your variant interface, and how it could be subclassed:
typedef std::ostream Out;
struct BadType {};
struct Var {
virtual ~Var () = default;
virtual Out & print (Out &os) { return os << "(BadType)"; }
virtual void set (int) { throw BadType(); }
virtual void set (const std::string &) { throw BadType(); }
};
struct VarInteger : Var {
int data;
VarInteger (int v) : data(v) {}
Out & print (Out &os) { return os << data; }
void set (int v) throw() { data = v; }
};
struct VarString : Var {
std::string data;
VarString (const std::string &v) : data(v) {}
Out & print (Out &os) { return os << data; }
void set (const std::string &v) throw() { data = v; }
};
Here is how you could define your pointer to pointer, and how they could be initialized:
typedef std::shared_ptr<Var> VarPtr;
std::shared_ptr<VarPtr> varptr_;
static VarPtr make_var () { return std::make_shared<Var>(); }
static VarPtr make_var (int v) { return std::make_shared<VarInteger>(v); }
static VarPtr make_var (const std::string &v) {
return std::make_shared<VarString>(v);
}
VarPtr & var () { return *varptr_; }
const VarPtr & var () const { return *varptr_; }
Container () : varptr_(std::make_shared<VarPtr>(make_var())) {}
Container (int v) : varptr_(std::make_shared<VarPtr>(make_var(v))) {}
Container (const std::string &v)
: varptr_(std::make_shared<VarPtr>(make_var(v))) {}
And here is how your set() methods and createLink() method could be implemented.
void set (int v) {
try { var()->set(v); }
catch (BadType) { var() = make_var(v); }
}
void set (const std::string &v) {
try { var()->set(v); }
catch (BadType) { var() = make_var(v); }
}
void createLink (const Container &val) { varptr_ = val.varptr_; }
Demo
How about the following. Of course createLink cannot not take a const reference so I made it to take a non-const pointer.
class Container {
const int STRING = 0x0000001;
const int INT = 0x0000002;
const int LINK = 0x8000000;
public:
...
void set(int val){...}
void set(const std::string &val)
{
if (var.type == LINK)
{
reinterpret_cast<Container*>(var.data)->set(val);
}
else
...
}
void createLink(Container* val)
{
var.data = val;
var.type = LINK;
}
private:
typedef struct VAR {
int type = 0;
void *data = NULL;
};
VAR var;
};
There are a some important points to think about - relative lifetimes of the link and the linked is the most obvious one.

Are there any alternatives to making const version of class?

In C++ I'm often facing a situation when I need to prepare const and non-const version of class in analogy to const_iterator and iterator from standard library.
class const_MyClass
{
public:
const_MyClass(const int * arr):
m_arr(arr)
{
}
int method() const; //does something with m_arr without modifying it
private:
const int * m_arr;
}
class MyClass
{
public:
MyClass(int * arr):
m_arr(arr)
{
}
int method() const; //does something with m_arr without modifying it
void modify(int i); //modify m_arr
private:
int * m_arr;
}
The problem with this is that I need to repeat whole code of const_MyClass in MyClass and distribute any changes in API to both classes. Thus sometimes I inherit const_MyClass and do some const_casts, which also isn't perfect and pretty solution. Still when I want to pass const_MyClass instance by reference it looks moronic:
void func(const const_MyClass & param)
Instance param is marked with two "consts", and it has only const methods...
This is where const constructors would be handy, but are there any existing alternatives?
Some use examples to explain problem better:
//ok to modify data
void f(int * data)
{
MyClass my(data);
my.modify();
...
}
//cant modify data, cant use MyClass
void fc(const int * data)
{
const_MyClass my(data);
int i = my.method();
...
}
You can make a template class to act as a base, like this:
template<typename T>
class basic_MyClass
{
public:
basic_MyClass(T * arr) :m_arr(arr) {}
int method() const; //does something with m_arr without modifying it
private:
T * m_arr;
};
Then, for your const version, since it doesn't add anything, you can just use a typedef:
typedef basic_MyClass<const int> const_MyClass;
For your non-const version, you can inherit:
class MyClass : public basic_MyClass<int>
{
public:
using basic_MyClass::basic_MyClass; // inherit all the constructors
void modify(int i); //modify m_arr
};
Have you considered simply tracking two pointers and raising exceptions from the mutable operations when no mutable value is available? Maybe an example will help describe what I am thinking of.
class MyClass
{
public:
MyClass(int *mutable_data):
m_mutable_view(mutable_data), m_readonly_view(mutable_data)
{
}
MyClass(const int *immutable_data):
m_mutable_view(NULL), m_readonly_view(immutable_data)
{
}
int retrieve_value(int index) {
return m_readonly_view[index];
}
void set_value(int index, int value) {
require_mutable();
m_mutable_view[index] = value;
}
protected:
void require_mutable() {
throw std::runtime_error("immutable view not available");
}
private:
const int *m_readonly_view;
int *m_mutable_view;
};
The idea is pretty simple here - use a sentinel value to indicate whether modifications are possible or not instead of depending on the type system to do that for you. Personally, I would think about doing the inheritance based approach that #BenjaminLindley suggested but I wanted to present a slightly different solution that might not have occurred to you.
After talk with Neil Kirk I realized what I was doing wrong. I started by separating data from logic as he suggested.
This attempt resulted in two classes MyClassPtr and const_MyClassPtr. They only provide functions for data access (like iterators) and may look like that:
class const_MyClassPtr
{
public:
const_MyClassPtr(const int * arr);
int operator [](int i) const;
const int * ptr() const;
private:
const int * m_arr;
}
class MyClassPtr
{
public:
MyClassPtr(int * arr);
int operator [](int i) const;
int & operator [](int i);
const int * ptr() const;
int * ptr();
//promotion to const pointer
const_MyClassPtr () const {return const_MyClassPtr(m_arr);}
private:
int * m_arr;
}
Now it is clear that objects of these classes should be treated like pointers, so when I use them as function parameters I pass them by value!
void func(const_MyClassPtr param) //instead of void func(const const_MyClass & param)
To provide methods I have created MyClassOp class template and used static polymorphism.
template <class DERIVED>
class MyClassOp
{
public:
const DERIVED & derived() const {return static_cast<const DERIVED &>(*this)}
DERIVED & derived() {return static_cast<DERIVED &>(*this)}
int method() const; //operates on derived() const
void modify(int i); //operates on derived()
}
MyClassOp is a collection of methods. It does not have state. In general it is a trait. To make these methods accessible I overloaded -> and * operators
class const_MyClassPtr : private MyClassOp<const_MyClassPtr>
{
public:
const MyClassOp<MyClassPtr> * operator ->() const {return this;}
const MyClassOp<MyClassPtr> & operator *() const {return *this;}
...
}
class MyClassPtr : private MyClassOp<MyClassPtr>
{
public:
MyClassOp<MyClassPtr> * operator ->() {return this;}
MyClassOp<MyClassPtr> & operator *() {return *this;}
...
}
This works O.K., but is a bit cumbersome. If I have for example equality operator I need to write something like *myptr1 == myptr2 to compare values kept by two MyClassPtr objects (it's easy to make a mistake and compare myptr1 == myptr2 or expect that something like *myptr1 == *myptr2 could work). Also when I have allocating type:
class MyClass : public MyClassOp<MyClass>
{
MyClass(int x, int y, int z);
...
int m_arr[3];
}
I would want to be able to use temporaries as function arguments.
void f(const_MyClassPtr my);
//use temporary when calling f()
f(MyClass(1, 2, 3));
I can do this by providing conversion operators or conversion constructors (that convert MyClass to const_MyClassPtr). But then const_MyClassPtr behaves more like reference than pointer. If iterators are generalization of pointers then why one could not imitate reference? Therefore I divided MyClassOp into two parts (const and non const) and replaced -> and * operators implemented by const_MyClassPtr and MyClassPtr with public inheritance and changed their names to ressemble reference. I ended up with following structures.
MyClassOp : public const_MyClassOp
const_MyClassRef : public const_MyClassOp<const_MyClassRef>
MyClassRef : public MyClassOp<MyClassRef>
MyClass : public MyClassOp<MyClass>
However const_MyClassRef and MyClassRef are not perfect generalization of reference as it impossible to imitate some of C++ reference properties, so Ref suffix is there to denote reference-like structure.
Maybe you can find some hints in effective c++ item 4 "Avoid duplication in const and non-const Member function"
I may summarize like following ( it makes you avoid code duplication even if using somewhat ugly cast ):
struct my_class
{
my_class(int x):_x(x){};
const int& method(void) const;
int& method(void);
int _x;
};
const int& my_class::method(void) const //func for const instance
{
return _x;
}
int& my_class::method(void) //func for normal instance
{
return const_cast<int& >(static_cast<const my_class& >(*this).method()) ;
}
int main()
{
my_class a(1);
const my_class b(2);
a.method() = 5;
cout << a.method() << endl;
//b.method() = 4; //b is const, wont compile
cout << b.method() << endl;
return 0;
}

Calling copy constructor from an unknown class without new

Here is the deal:
I have a templated class C
template<class T>
class C;
that has a member that is basically a pointer to a reinterpretation of T called P (don't worry about P)
P* reint;
what I want to do is a method that receives a T and copies it into reint
void foo (T& param) {
new (reint) (param);
}
problem is the compiler is giving out warnings that reint is not a T that I want to get rid of. My first idea was to reinterpret reint into a T:
void foo (T& param) {
new (reinterpret_cast<T&>(*reint)) T(param);
}
but the compiler started giving me an error saying
invalid conversion from const void* to void*
So i looked it up and new is defined as such:
void* operator new (std::size_t size, void* ptr) throw();
So for some reason my casting is turning reint into a const void*.
New idea: cast reint to a T and call the copy constructor. Problem: no clue how to call the copy constructor from an unknown class.
(maybe
reinterpret_cast<T>(*reint).T(param);
?)
Could you help me please?
Maybe you want something like:
#include <stdexcept>
struct Data
{
const std::string value;
Data(const std::string& value)
: value(value)
{}
Data(const Data& other) = default;
Data& operator = (const Data& other) = delete;
};
template <typename T>
class Holder
{
public:
Holder() = default;
Holder(const T& data) {
assign(data);
}
~Holder() {
release();
}
void assign(const T& data) {
release();
new (m_data) T(data);
m_valid = true;
}
void release() {
if(m_valid) {
reinterpret_cast<T*>(m_data)->~T();
m_valid = false;
}
}
const T& get() const {
if( ! m_valid) throw std::runtime_error("Invalid");
return *reinterpret_cast<const T*>(m_data);
}
private:
bool m_valid = false;
char m_data[sizeof(T)];
};
#include <iostream>
int main() {
Holder<Data> holder;
holder.assign(Data("Hello"));
const Data& data = holder.get();
std::cout << data.value << '\n';
}
You're going the wrong way, you want somethng more like:
reint = reinterpret_cast<P*>(param);
The solution was to make a struct to return the reinterpreted P for both const and unconst
template <class T> struct Temp {
T* switch (P* r) { return reinterpret_cast<T*>(r); }
}
template <class T> struct Temp <const T> {
T* switch (P* r) { return reinterpret_cast<T*>(r); }
}
then use the struct to remove const from reint
new (Temp::switch(reint)) T(param);

Memory Read Error while accessing pointers in object

I have subdivided my question into different sections for better understanding. They are as below:
A) Classes My Question is related to
I have a class TLst representing list as below:
template <class TVal>
class TLst{
public:
typedef TLstNd<TVal>* PLstNd;
private:
int Nds;
PLstNd FirstNd;
PLstNd LastNd;
public:
TLst(): Nds(0), FirstNd(NULL), LastNd(NULL){}
TLst(const TLst&);
~TLst(){Clr();}
explicit TLst(TSIn& SIn);
void Save(TSOut& SOut) const;
**TLst <TVal>& operator = (const TLst <TVal> &t)
{
TLst<TVal>::PLstNd Nd;
if (Len()!=t.Len()) { Clr(); }
for (TLst<TVal>::PLstNd np = t.First(); np!=NULL ; np=np->Next()) {
Nd = AddBack(np->GetVal());
}
return *this;
}**
void Clr(){
PLstNd Nd=FirstNd;
while (Nd!=NULL){PLstNd NextNd=Nd->NextNd; delete Nd; Nd=NextNd;}
Nds=0; FirstNd=NULL; LastNd=NULL;}
bool Empty() const {return Nds==0;}
int Len() const {return Nds;}
PLstNd First() const {return FirstNd;}
PLstNd Last() const {return LastNd;}
**PLstNd AddBack(const TVal& Val){
PLstNd Nd=new TLstNd<TVal>(LastNd, NULL, Val);
if (LastNd!=NULL){LastNd->NextNd=Nd; LastNd=Nd;}
else {FirstNd=Nd; LastNd=Nd;}
Nds++; return Nd;
}**
PLstNd AddFrontSorted(const TVal& Val, const bool& Asc=true);
PLstNd AddBackSorted(const TVal& Val, const bool& Asc=true);
void PutFront(const PLstNd& Nd);
void PutBack(const PLstNd& Nd);
PLstNd Ins(const PLstNd& Nd, const TVal& Val);
void Del(const TVal& Val);
void Del(const PLstNd& Nd);
PLstNd SearchForw(const TVal& Val);
PLstNd SearchBack(const TVal& Val);
friend class TLstNd<TVal>;
};
Similarly I have the class TLstNd to represent a list-node as below:
template <class TVal>
class TLstNd{
public:
TLstNd* PrevNd;
TLstNd* NextNd;
TVal Val;
public:
TLstNd(): PrevNd(NULL), NextNd(NULL), Val(){}
TLstNd(const TLstNd&);
**TLstNd(TLstNd* _PrevNd, TLstNd* _NextNd, const TVal& _Val):
PrevNd(_PrevNd), NextNd(_NextNd), Val(_Val){}**
TLstNd& operator=(const TLstNd&);
TLstNd* Prev() const {Assert(this!=NULL); return PrevNd;}
TLstNd* Next() const {Assert(this!=NULL); return NextNd;}
TVal& GetVal(){Assert(this!=NULL); return Val;}
};
And I have the members and constructors of class TVec (not the entire class) as shown below
template <class TVal>
class TVec{
public:
typedef TVal* TIter;
protected:
int MxVals; // if MxVals==-1, then ValT is not owned by us, we don't free it!
int Vals;
TVal* ValT;
void Resize(const int& _MxVals=-1);
TStr GetXOutOfBoundsErrMsg(const int& ValN) const;
public:
TVec(): MxVals(0), Vals(0), ValT(NULL){}
TVec(const TVec& Vec);
**explicit TVec(const int& _Vals){
IAssert(0<=_Vals); MxVals=Vals=_Vals;
if (_Vals==0){ValT=NULL;} else {ValT=new TVal[_Vals];}}**
TVec(const int& _MxVals, const int& _Vals){
IAssert((0<=_Vals)&&(_Vals<=_MxVals)); MxVals=_MxVals; Vals=_Vals;
if (_MxVals==0){ValT=NULL;} else {ValT=new TVal[_MxVals];}}
explicit TVec(TVal *_ValT, const int& _Vals):
MxVals(-1), Vals(_Vals), ValT(_ValT){}
...
};
And I have the class TPair as below:
class TPair{
public:
TVal1 Val1;
TVal2 Val2;
public:
TPair(): Val1(), Val2(){}
TPair(const TPair& Pair): Val1(Pair.Val1), Val2(Pair.Val2){}
**TPair(const TVal1& _Val1, const TVal2& _Val2): Val1(_Val1), Val2(_Val2){}**
...
TPair& operator=(const TPair& Pair){
if (this!=&Pair){Val1=Pair.Val1; Val2=Pair.Val2;} return *this;}
bool operator==(const TPair& Pair) const {
return (Val1==Pair.Val1)&&(Val2==Pair.Val2);}
...
};
B) What I am doing?
a) I have a TVec>> class "typedef"-ed as
typedef TVec<TPair<TInt, TLst<TInt>>> TNdClass;
b) Next, I create an object of TNdClass, as
TNdClass UsrClassList(MXCLASS_SIZE); //calls TVec(const int& _Vals)
If you see the TVec constructor which is bold, the above call sets Vals, MxVals and allocates MxVals memory for ValT which means UsrClassList allocates memory of size MXCLASS_SIZE*sizeof(TPair>).
c) Next, I am assigning Val1 (of type TInt) and Val2 (of type TLst) to two variables NdCnt (of type TInt) and Nodes (of type TLst). And declare a variable NdClss of type TPair> as below:
TInt NdCnt(0);
TLst<TInt> Nodes;
NdCnt = UsrClassList[VecIdx].Val1; //assigning TInt to TInt
Nodes = UsrClassList[VecIdx].Val2; //assigning TLst<TInt> to TLst<TInt>
TPair<TInt, TLst<TInt> > NdClss; //declaration
d) Next I am adding a TInt of value 1 to Nodes using the AddBack function of TLst (see above in bold) and assign a TPair object instantiated with NdCnt and Nodes to NdClassas below:
Nodes->AddBack(1); //adding a TInt of value 1 to Nodes
e) Finally I am creating a new object of type TPair with NdCnt and Nodes values as parameter and is assigning to NdClss variable (type TPair) declared in step c).
NdClss = TPair<TInt, TLst<TInt>>(NdCnt, Nodes);
This step ends up with an exception with memory read error.
Further down the code, when I am debugging the values of Nodes.First()->NextNd or Nodes.First()->PrevNd the compiler gives "memory read error" which I feel indicates that the NextNd and PrevNd pointers are not allocated with memory.
When I debug the code, I get the value '???' for the watch variables PrevNd and NextNd:
- FirstNd 0x00e6b830 {PrevNd=0x00000000 NextNd=0x00000000 Val={...} } TLstNd<TInt> *
+ PrevNd 0x00000000 {PrevNd=??? NextNd=??? Val={...} } TLstNd<TInt> *
+ NextNd 0x00000000 {PrevNd=??? NextNd=??? Val={...} } TLstNd<TInt> *
+ Val {Val=0 Mn=-2147483648 Mx=2147483647 ...} TInt
- LastNd 0x00e6b830 {PrevNd=0x00000000 NextNd=0x00000000 Val={...} } TLstNd<TInt> *
+ PrevNd 0x00000000 {PrevNd=??? NextNd=??? Val={...} } TLstNd<TInt> *
+ NextNd 0x00000000 {PrevNd=??? NextNd=??? Val={...} } TLstNd<TInt> *
+ Val {Val=0 Mn=-2147483648 Mx=2147483647 ...} TInt
Any suggestions of why the memory for Nodes.First()->NextNd and Nodes.First()->PrevNd are not allocated? And what I need to do to allocate the memory of those two pointers in TLst class?
Look forward to replies.
Somnath
I will try to answer. But my eyes are bleeding right now after reading your question...
For your first question :
I do not see in your code the allocation of TLstNd::PrevNd and TLstNd::NextNd.
And you are saying that you are having a memory read error after accessing to these members...
May be you should allocate them...
For your second question :
Use the keyword new to allocate objects...

Generic object carrier class - C++

I need to create a generic object carrier class. I came up with something simple like
template<typename T>
class ObjectCarrier
{
public:
const T& item() const
{
return item_;
}
void setItem(T& item)
{
item_ = item;
}
private:
T item_;
};
This works well when T has got a default constructor (parameterless). Things gets complicated when T has parameterized constructors. So I rewrote the class like
template<typename T>
class ObjectCarrier
{
public:
const T& item() const
{
return *item_;
}
void setItem(T& item)
{
item_ = new T ( item );
}
private:
T* item_;
};
Changed the item_ variable to T* and created a new instance using the copy constructor of T. Again this worked well until T is a pointer type. I mean ObjectCarrier<Foo*> won't work.
I am wondering how can I design this class so that it works for almost all kind of types. I think I may need to create a traits type specialized for pointers. But unfortunately, I am not able to make that work.
Any help would be great.
The above approaches are way way too complicated. Keep it simple, and just solve the constructor arg problem by using template constructors. Don't use pointers, they will create object lifetime and copying headaches.
Here's an implementation I use a lot. The template constructors will forward arguments for things directly on to the nested object which is convenient. The operator T& values let you pass carrier<T> to functions that take a type T, without expensive copying. You can wrap objects that take up to two arguments with this code.
/* A wrapper of type T */
template <typename T>
struct carrier {
carrier() {}
template <typename A1> carrier(const A1& a1) : value(a1) {}
template <typename A1, typename A2> carrier(const A1& a1, const A2& a2) : value(a1, a2) {}
operator T&() { return value; }
operator const T&() const { return value; }
T value;
};
You can use it like this:
const carrier<point> p1(10,10); // make p1 const to stop people changing it
showPoint(p1); // calls a function that expects a point,
showPoint(p1.value); // access the point directly
You can use template specialization for the T* type and rewrite the methods to suite pointers. You can do something like:
template<typename T>
class ObjectCarrier<T*>
{
public:
const T* item() const
{
return item_;
}
void setItem(T* item)
{
item_ = item;
}
private:
T* item_;
};
There is a design patern that is possibly relevant to this - Memento.
A bit off topic, but bear in mind that as soon as you start newing objects up inside your class, you'll need a way to manage the memory. I'd suggest using an std::auto_ptr at the least. You'll also need to provide a copy constructor and an assignment operator, when using std::auto_ptr.
It might be possible to hold the object by value and still defer its construction with the use of placement new and something like the following:
#include <iostream>
#include <cassert>
template <class T>
class ObjectCarrier
{
public:
ObjectCarrier(): ref(0) {}
ObjectCarrier(const ObjectCarrier& other): ref(0)
{
set_data(other.ref);
}
~ObjectCarrier()
{
clear();
}
const ObjectCarrier& operator = (const ObjectCarrier& other)
{
if (other.empty())
clear();
else
set_data(other.ref);
return *this;
}
void set(const T& value)
{
set_value(value);
}
const T& get() const
{
assert(!empty() && "No object being carried");
return *ref;
}
bool empty() const
{
return ref == 0;
}
void clear()
{
if (!empty()) {
ref->~T();
ref = 0;
}
}
private:
char data[sizeof(T)];
T* ref;
void set_value(const T& value)
{
if (!empty()) {
*ref = value;
}
else {
ref = new (data) T(value);
}
}
void set_data(const T* value)
{
if (value) {
set_value(*value);
}
}
};
int main()
{
ObjectCarrier<int> i;
ObjectCarrier<int> j(i);
i = j;
i.set(10);
std::cout << i.get() << '\n';
j = i;
i.set(20);
std::cout << i.get() << ' ' << j.get() << ' ' << ObjectCarrier<int>(i).get() << '\n';
}
However, I would somewhat question the usefulness of this class. Perhaps the only purpose it could have, would be to act as Boost.Optional.
But if you don't want the class to be able to not hold a value, just give it a parametrized constructor:
template<typename T>
class ObjectCarrier
{
public:
ObjectCarrier(const T& value = T()):
item_(value)
{
}
const T& item() const
{
return item_;
}
void setItem(T& item)
{
item_ = item;
}
private:
T item_;
};
(It's just that this class seems rather useless, unless perhaps as a facade for code that expects variables to have item and setItem methods, rather than, say, an assignment operator.)
boost::optional does something very similar to this (also boost::any, but nevermind).
You can check out how its implemented at: http://cplusplus.co.il/2009/12/04/boost-optional-and-its-internals/ and don't worry - it's pretty straightforward.