I'm trying to code my own implementation of shared pointers (for fun/challenge) but I hit a dead end after I cannot make the constructor accept any (auto) type of pointer variable. The problem is, for now I can only make my own smart pointer points to a certain data-type (class P) but I want it to be able to point to any data type however the problem is I need to specify the data type in the constructor arguments.
Code:
#include <iostream>
#include <memory>
class P //dummy class
{
int x;
public:
P() : x(42) {}
~P() {}
void print()
{
std::cout<<"Address = "<< this << "\n";
}
};
class P2 //dummy class 2
{
public:
P2() {}
~P2() {}
void print()
{
std::cout<<"Address = "<< this << "\n";
}
};
class SmartP
{
P *ptr;
public:
SmartP(P *p) : ptr(p) {}
~SmartP()
{
delete ptr;
}
P& operator* ()
{
return *ptr;
}
P* operator-> ()
{
return ptr;
}
};
void rawPointer()
{
P *p(new P);
p->print();
delete p; //when removed, next allocated address will be different
}
void smartPointerOwn()
{
SmartP spo(SmartP(new P));
//This should also work but currently it does not: SmartP spo(SmartP(new P2));
spo->print();
//Do not need a delete
}
void smartPointer()
{
std::unique_ptr<P> sp(new P);
sp->print();
//Do not need a delete
}
int main()
{
rawPointer();
smartPointerOwn();
smartPointer();
std::cin.get(); //Prevent exiting console prematurely
return 0;
}
Thanks!
here some basic example to help start you off. Like already mentioned in the comments you should first check some existing smart pointer implementations.
This example is very incomplete - for ex. the reference counting is missing (if shared pointer wanted). But it gives you an idea. I hope it helps a little bit.
#include <iostream>
using namespace std;
template <typename T>
class SmartP {
public:
SmartP() : p{nullptr} {}
SmartP(T* pp) : p{pp} {}
~SmartP() { delete p; }
// dereferencing operators
friend T& operator*(const SmartP<T>& sp) { return *(sp.p); }
T& operator->() const { return *p; }
// get the raw pointer
T* get() const { return p; }
private:
T* p;
};
int main() {
SmartP<int> p{new int{3}};
cout << *p << endl;
*p = 4;
cout << *p << endl;
}
Related
Assume the snippet below. How can I make this compiling/working? I do not want to move print to the String/Float class, because in my real world situation this function is combining a lot of data.
So basically I want a pointer/member to "any type (in this case string/float)" then use it, and call dynamically something else (in this case print)?
I assume that this does not work (among others) because it cannot determine at compile time which type T of ptr will have at compile time.
What is the general pattern to solve such kind of problems?
#include <iostream>
template<typename T>
class AbstractClass {
virtual T getValue()=0;
};
class StringClass : public AbstractClass<std::string> {
std::string getValue() override {
return "A";
}
};
class FloatClass : public AbstractClass<float> {
float getValue() override {
return 1;
}
};
class Processor {
public:
AbstractClass<T>* ptr;
void doIt() {
ptr=new StringClass();
print(ptr->getValue());
delete ptr;
ptr=new FloatClass();
print(ptr->getValue());
delete ptr;
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}
If you want an object that's 'one of' a given set of types, you can use std::variant<Ts...>. Mathematically, it represents discriminated/tagged union. This way, you don't need a pointer, neither a base class. Example:
#include <iostream>
#include <variant>
class StringClass {
std::string getValue() override {
return "A";
}
};
class FloatClass {
float getValue() override {
return 1;
}
};
using ClassWithGetValue = std::variant<StringClass, FloatClass>;
class Processor {
public:
ClassWithGetValue v;
void doIt() {
v = StringClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
v = FloatClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}
I have a World class and a Entity class.
The World class creates new Entites and retuns a pointer to it.
If i use that pointer im never sure if that pointer is still pointing to a valid Entity but i also dont want to use a shared_ptr because the Entity wont get deleted until all shared_ptr are released. So after some time i cameup with this pointer:
#include <iostream>
#include <unordered_map>
template<class T>
class Pointer
{
public:
Pointer() :m_ptr(nullptr){}
Pointer(T*p) :m_ptr(p) { m_ptr->addPtr(this); }
~Pointer() { if(valid()) m_ptr->removePtr(this); }
Pointer(const Pointer &other) :m_ptr(other.m_ptr)
{
if(valid())
m_ptr->addPtr(this);
}
Pointer& operator=(const Pointer& other)
{
if (valid())
m_ptr->removePtr(this);
m_ptr = other.m_pObj;
if (valid())
m_ptr->addPtr(this);
return *this;
}
T* operator->() { return m_ptr; }
T* operator*() { return *m_ptr; }
T* get() { return m_ptr; }
bool valid() { return m_ptr != nullptr; }
private:
template<typename T>
friend class PointerCollector;
T * m_ptr;
};
template <class T>
class PointerCollector
{
public:
PointerCollector() = default;
virtual ~PointerCollector()
{
for (auto &x : m_ptrList)
{
(x.second)->m_ptr = nullptr;
}
}
private:
void addPtr(Pointer<T> *ptr)
{
m_ptrList[ptr] = ptr;
}
void removePtr(Pointer<T> *ptr)
{
m_ptrList.erase(ptr);
}
template<typename T>
friend class Pointer;
std::unordered_map<Pointer<T>*, Pointer<T>*> m_ptrList;
};
class Test : public PointerCollector<Test>
{
public:
Test() {}
~Test() = default;
int getVal() { return m_val; }
private:
int m_val = 100;
};
void func(Pointer<Test> ptr)
{
if (ptr.valid())
{
std::cout << ptr->getVal();
}
else
{
std::cout << "Invalid!\n";
}
}
int main()
{
Test* myTest = new Test();
Pointer<Test> myPtr(myTest);
Pointer<Test> myPtr2(myPtr);
delete myTest;
func(myPtr2);
getchar();
return 0;
}
the Test class will collect the pointers to it and invalidates them if the class gets deleted.
Now i wanted to ask if anyone knows a better implementation or more infomation about this kind of pointer.
I compiled and tested the above code in Visual Studio 2017
The answer is yes, this pattern has been used before by many people. You just created a poor (and broken, because there's at least one outright bug and several things that are sub-optimal) re-implementation of ::std::weak_ptr<T>. You should consider using it instead.
I'm trying to write a class that accepts a a function pointer AND/OR a functor to be user later by the class.
To illustrate better what I'd like to do:
template <typename T> class Holder {
private:
T *m_ptr;
<something> m_func;
public:
Holder(T *ptr) : m_ptr(ptr), m_func(NULL) {
}
Holder(T *ptr, <something> func) : m_ptr(ptr), m_func(func) {
}
~Holder() {
if (m_func) {
m_func(m_ptr);
} else {
delete m_ptr;
}
}
};
Considering I'd like to handler objects of this type:
class MyClass {
public:
void describe() {
cout << "Bla bla bla ...";
}
};
Then I could use it this way:
class MyClassFunctor {
public:
void operator()(MyClass *ptr) const {
cout << "Deleting ptr using functor: ";
ptr->describe();
cout << endl;
delete ptr;
}
};
int main() {
MyClass *myclass = new MyClass();
MyClassFunctor functor();
{
Holder<MyClass> holder(myClass, functor);
}
cout << "I'm out of context now!" << endl;
}
AND (not or) this way:
void myClassDeleter(MyClass *ptr) {
cout << "Deleting ptr using function pointer: ";
ptr->describe();
cout << endl;
delete ptr;
}
int main() {
MyClass *myclass = new MyClass();
{
Holder<MyClass> holder(myClass, &myClassDeleter);
}
cout << "I'm out of context now!" << endl;
}
Notice I'd like to be able to use both approaches: Functors AND function pointers.
I'd say it is possible, since this is what Boost::shared ptr and tr1::shared_ptr does.
I tried digging into Boost::shared_ptr code, but I couldn't really understand how they do it.
I'm sorry if my code is wrong or seems to be naive. I tried to explain the problem as concisely as possible, so code correctness wasn't my main focus here (I realize this is important).
Notice I don't even think about rewriting a smart pointer class from scratch. This is out of question here, since I know it is not a wise call.
I'm interested in knowing how to do it so I can use this mechanism for other purposes. Smart pointers were simply the simplest use of that I could remember.
For now, I'd like to avoid using boost and C++11. Is it possible to do it using plain c++03?
Thanks very much for your time.
The answer is: Type Erasure.
The implementation is not that simple, and I suggest reading about Type Erasure a little (as I just did!).
First of all, you need to create the Type Erased apparatus:
class ActionBase {
public:
virtual ~ActionBase() { }
virtual bool DoIt() = 0;
};
template<typename P>
class ActionP : public ActionBase {
private:
P *ptr;
public:
ActionP(P *p) : ptr(p) { }
virtual bool DoIt() {
cout << "Standard action (nothing to do)..." << endl;
return true;
}
};
template<typename P, class A>
class ActionPA : public ActionBase {
private:
P *ptr;
A action;
public:
ActionPA(P *p, A & a ) : ptr(p), action(a) { }
virtual bool DoIt() { return action(ptr); }
};
Then you can declare the Holder class:
template<typename T>
class Holder {
private:
// Avoid object copy and assignment.
Holder(const Holder<T> &rhs);
Holder<T>& operator=(const Holder<T> &rhs);
protected:
T* ptr;
ActionBase *action;
public:
template<typename U> Holder(U *ptr) : ptr(ptr), action(new ActionP<U>(ptr)) { }
template<typename U, class A> Holder(U* p, A a) : ptr(p), action(new ActionPA<U, A>(p, a)) { }
virtual ~Holder() { delete ptr; delete action; }
bool DoAction() {
return this->action->DoIt();
}
};
Then you can use it passing function pointers, functors, or even nothing:
template<typename T>
class ActionFunctor {
public:
bool operator()(T* instance) const {
cout << "Action operator..." << endl;
// Simple operation: set the value to 3 times the original value (works for int and string!!)
instance->Set(instance->Get() + instance->Get());
return true;
}
};
template<typename T>
bool ActionFunc(T* instance) {
cout << "Action function..." << endl;
// Simple operation: set the value to 3 times the original value (works for int and string!!)
instance->Set(instance->Get() + instance->Get() + instance->Get());
return true;
}
int main() {
{
cout << "First test:" << endl;
ActionFunctor<X> actionX;
Holder<X> x1(new X(1), &ActionFunc<X>);
Holder<X> x2(new X(10), actionX);
Holder<X> x3(new X(100));
x1.DoAction();
x2.DoAction();
x3.DoAction();
}
{
cout << "Second test:" << endl;
ActionFunctor<Y> actionY;
Holder<Y> y1(new Y("A"), &ActionFunc<Y>);
Holder<Y> y2(new Y("BB"), actionY);
Holder<Y> y3(new Y("CCC"));
y1.DoAction();
y2.DoAction();
y3.DoAction();
}
return 0;
}
Here is the output:
First test:
X constructor: 1
X constructor: 10
X constructor: 100
Action function...
Action operator...
Standard action (nothing to do)...
X desstructor: 100
X desstructor: 20
X desstructor: 3
Second test:
Y constructor: "A"
Y constructor: "BB"
Y constructor: "CCC"
Action function...
Action operator...
Standard action (nothing to do)...
Y destructor: "CCC" ...
Y destructor: "BBBB" ...
Y destructor: "AAA" ...
Hope it's useful for someone else.
One obvious solution is to use boost::function or std::function. However, if you want to avoid the overhead these objects add, you can make Holder to accept a Callable as a template argument:
template <typename T, class F>
class Holder
{
private:
T *m_ptr;
F m_func;
//...
Of course, you'd have to make a helper function that would deduct the actual type of the Callable:
// depending on the nature of your functors, consider passing by const &
template<typename T, class F>
Holder<T, F> make_holder(T *t, F f)
{
return Holder<T, F>(t, f);
}
Use it like this:
auto holder = make_holder(myClass, &myClassDeleter);
// or:
auto holder = make_holder(myClass, functor);
My use is pretty complicated. I have a bunch of objs and they are all passed around by ptr (not reference or value unless its an enum which is byval). At a specific point in time i like to call CheckMembers() which will check if each member has been set or is null. By default i cant make it all null because i wouldnt know if i set it to null or if it is still null bc i havent touch it since the ctor.
To assign a variable i still need the syntax to be the normal var = p; var->member = new Type;. I generate all the classes/members. So my question is how can i implement a property like feature where i can detect if the value has been set or left as the default?
I am thinking maybe i can use C++ with CLR/.NET http://msdn.microsoft.com/en-us/library/z974bes2.aspx but i never used it before and have no idea how well it will work and what might break in my C++ prj (it uses rtti, templates, etc).
Reality (edit): this proved to be tricky, but the following code should handle your requirements. It uses a simple counter in the base class. The counter is incremented once for every property you wish to track, and then decremented once for every property that is set. The checkMembers() function only has to verify that the counter is equal to zero. As a bonus, you could potentially report how many members were not initialized.
#include <iostream>
using namespace std;
class PropertyBase
{
public:
int * counter;
bool is_set;
};
template <typename T>
class Property : public PropertyBase
{
public:
T* ptr;
T* operator=(T* src)
{
ptr = src;
if (!is_set) { (*counter)--; is_set = true; }
return ptr;
}
T* operator->() { return ptr; }
~Property() { delete ptr; }
};
class Base
{
private:
int counter;
protected:
void TrackProperty(PropertyBase& p)
{
p.counter = &counter;
counter++;
}
public:
bool checkMembers() { return (counter == 0); }
};
class OtherObject : public Base { }; // just as an example
class MyObject : public Base
{
public:
Property<OtherObject> x;
Property<OtherObject> y;
MyObject();
};
MyObject::MyObject()
{
TrackProperty(x);
TrackProperty(y);
}
int main(int argc, char * argv[])
{
MyObject * object1 = new MyObject();
MyObject * object2 = new MyObject();
object1->x = new OtherObject();
object1->y = new OtherObject();
cout << object1->checkMembers() << endl; // true
cout << object2->checkMembers() << endl; // false
delete object1;
delete object2;
return 0;
}
There are a number of ways to do this, with varying tradeoffs in terms of space overhead. For example, here's one option:
#include <iostream>
template<typename T, typename OuterClass>
class Property
{
public:
typedef void (OuterClass::*setter)(const T &value);
typedef T &value_type;
typedef const T &const_type;
private:
setter set_;
T &ref_;
OuterClass *parent_;
public:
operator value_type() { return ref_; }
operator const_type() const { return ref_; }
Property<T, OuterClass> &operator=(const T &value)
{
(parent_->*set_)(value);
return *this;
}
Property(T &ref, OuterClass *parent, setter setfunc)
: set_(setfunc), ref_(ref), parent_(parent)
{ }
};
struct demo {
private:
int val_p;
void set_val(const int &newval) {
std::cout << "New value: " << newval << std::endl;
val_p = newval;
}
public:
Property<int, demo> val;
demo()
: val(val_p, this, &demo::set_val)
{ }
};
int main() {
demo d;
d.val = 42;
std::cout << "Value is: " << d.val << std::endl;
return 0;
}
It's possible to get less overhead (this has up to 4 * sizeof(void*) bytes overhead) using template accessors - here's another example:
#include <iostream>
template<typename T, typename ParentType, typename AccessTraits>
class Property
{
private:
ParentType *get_parent()
{
return (ParentType *)((char *)this - AccessTraits::get_offset());
}
public:
operator T &() { return AccessTraits::get(get_parent()); }
operator T() { return AccessTraits::get(get_parent()); }
operator const T &() { return AccessTraits::get(get_parent()); }
Property &operator =(const T &value) {
AccessTraits::set(get_parent(), value);
return *this;
}
};
#define DECL_PROPERTY(ClassName, ValueType, MemberName, TraitsName) \
struct MemberName##__Detail : public TraitsName { \
static ptrdiff_t get_offset() { return offsetof(ClassName, MemberName); }; \
}; \
Property<ValueType, ClassName, MemberName##__Detail> MemberName;
struct demo {
private:
int val_;
struct AccessTraits {
static int get(demo *parent) {
return parent->val_;
}
static void set(demo *parent, int newval) {
std::cout << "New value: " << newval << std::endl;
parent->val_ = newval;
}
};
public:
DECL_PROPERTY(demo, int, val, AccessTraits)
demo()
{ val_ = 0; }
};
int main() {
demo d;
d.val = 42;
std::cout << "Value is: " << (int)d.val << std::endl;
return 0;
}
This only consumes one byte for the property struct itself; however, it relies on unportable offsetof() behavior (you're not technically allowed to use it on non-POD structures). For a more portable approach, you could stash just the this pointer of the parent class in a member variable.
Note that both classes are just barely enough to demonstrate the technique - you'll want to overload operator* and operator->, etc, as well.
Here's my temporary alternative. One that doesn't ask for constructor parameters.
#include <iostream>
#include <cassert>
using namespace std;
template <class T>
class Property
{
bool isSet;
T v;
Property(Property&p) { }
public:
Property() { isSet=0; }
T operator=(T src) { v = src; isSet = 1; return v; }
operator T() const { assert(isSet); return v; }
bool is_set() { return isSet; }
};
class SomeType {};
enum SomeType2 { none, a, b};
class MyObject
{
public:
Property<SomeType*> x;
Property<SomeType2> y;
//This should be generated. //Consider generating ((T)x)->checkMembers() when type is a pointer
bool checkMembers() { return x.is_set() && y.is_set(); }
};
int main(int argc, char * argv[])
{
MyObject* p = new MyObject();
p->x = new SomeType;
cout << p->checkMembers() << endl; // false
p->y = a;
cout << p->checkMembers() << endl; // true
delete p->x;
delete p;
}
I have created a smart pointer implementation as given below ::
#include <iostream>
#include <vector>
using namespace std;
class Obj {
int i, j;
public:
Obj() { i = 0 ; j = 0 ; }
Obj(int ii , int jj) : i(ii) , j(jj) { }
void f() { cout << i << endl; }
void g() { cout << j << endl; }
};
class ObjDerived : public Obj
{
int k;
public:
ObjDerived(int kk = 0) :k(kk) { }
void h() { cout << k << endl; }
};
template <typename ULT >
class SP
{
ULT* ptr;
public:
explicit SP(ULT* tptr = NULL) : ptr(tptr) { }
template <typename OTHER>
SP(SP<OTHER>& other)
{
ptr = (ULT*)other.ptr;
}
ULT* operator->() { return ptr; }
ULT& operator*() { return *ptr; }
SP<ULT>& operator=(SP<ULT>& tptr)
{
if(ptr != tptr.ptr)
ptr = tptr.ptr;
return *this;
}
SP<ULT>& operator=(ULT* tptr)
{
ptr = tptr;
return *this;
}
template <typename OTHER>
SP<ULT>& operator=(SP<OTHER>& der) // ??
{
cout << "In operator\n";
this->ptr = (ULT*)der.ptr;
return *this;
}
~SP()
{
if(ptr != NULL )
delete ptr;
}
};
int main()
{
SP<Obj> Sptr2(new Obj(10,20));
SP<ObjDerived> Sptr4(new ObjDerived(80));
Sptr2 = Sptr4; //error in this line
return 0;
}
I am trying to cast a derived class pointer to base class pointer using smart pointer SP . The operator= member function
template <typename OTHER>
SP<ULT>& operator=(SP<OTHER>& der) // ??
{
cout << "In operator\n";
this->ptr = (ULT*)der.ptr;
return *this;
}
is giving the following error ---> error: 'ObjDerived* SP::ptr' is private
I am not able to find out how to achieve the desired pointer conversion using smart pointer. I also searched previous posts on smart pointers but could not find exact answer to my problem.
You can provide public get() function member to be able to retrieve raw pointer. Commonly smart pointers provide this functionality. Small example:
template <typename ULT >
class SP {
// ...
ULT* get() const {return ptr;}
template <typename OTHER>
SP<ULT>& operator=(SP<OTHER>& der) {
cout << "In operator\n";
this->ptr = (ULT*)der.get();
return *this;
}
};
Also you can see Item 45 of Effective C++ for more information about creating smart pointer.
I assumed you are doing this for training tasks, because there are quite good smart pointers implementation, for example, boost::shared_ptr.
Well the member ptr is private - make it public or provide a public access method.
Have you considered using Boost smart pointers instead of attempting to roll your own? They've already gone through all the pain of implementing good smart pointer classes. Even if for some reason you can't use Boost, you can still learn a lot from their classes.
You can make member ptr as private. Or you can use in-built copy mechanism:
Instead of,
this->ptr = (ULT*)der.ptr; // ptr needs to be accessible
Do following:
*this = *((ULT*&)der); // copy using in-built shallow copy