In order to provide a simple "garbage collector" for my programs, I'm trying to write a template smart-pointer class, that may be used like that :

#include <ref.h>

class Foobar{ ....};

ref<Foobar> sample_manipulation(ref<Foobar> in)
{
    ref<Foobar> f=in;
    //....
    return f;
}

int main(void)
{
    ref<Foobar> f1=new Foobar;
    ref<Foobar> f2;
    f2=sample_manipulation(f1);
    return 0;
}

I Just cannot compile the code : g++ says :

: error: no match for 'operator=' in 'f2 = sample_manipulations(ref<Foobar>)()'
ref.h:71: note: candidates are: ref<T>& ref<T>::operator=(ref<T>&) [with T = Foobar]

Does someone know where is the problem ?

Thanx

Recommended Answers

All 10 Replies

Yes. I believe it is beacuse you defined you operator = with just a reference and not a value. Which the sample_manipulation returns.

#ifndef REF_H
#define REF_H

template<typename T> class ref;

template<typename T1, typename T2>
ref<T1> ref_cast(ref<T2>& r2)
{
	return ref<T1>(static_cast<T1>(r2.c_ptr()), r2.num_ref()+1);
}

template<typename T>
class ref
{
	private :

	T* _ptr;
	unsigned long *_ref_count;

	public :

	inline explicit ref(T* ptr) : _ptr(ptr), _ref_count(new unsigned long)
	{
		*_ref_count=1;
	}

	inline ref() : _ptr(0), _ref_count(new unsigned long)
	{
		*_ref_count=0;
	}

	inline ref(const ref<T>& copied)
	{
		_ref_count=copied._ref_count;
		_ptr=copied._ptr;
		(*_ref_count)++;
	}


	inline ~ref()
	{
		*_ref_count-=*_ref_count?1:0;
		if(*_ref_count == 0)
		{
			delete _ref_count;
			delete _ptr;
		}
	}

	inline T* operator->()
	{
		return _ptr;
	}

	inline bool operator!()
	{
		return _ptr==0;
	}

	inline bool operator==(ref<T>& r1)
	{
		return *((T*)_ptr)==*((T*)r1._ptr);
	}

	inline bool operator!=(ref<T>& r1)
	{
		return *((T*)_ptr)!=*((T*)r1._ptr);
	}

	inline ref<T>& operator=(ref<T>& r1)
	{
		*_ref_count-=*_ref_count?1:0;
		_ref_count=r1._ref_count;
		_ptr=r1._ptr;
		(*_ref_count)++;
		return *this;
	}
	//added this 
	inline ref<T>& operator=(ref<T> r1)
	{
		*_ref_count-=*_ref_count?1:0;
		_ref_count=r1._ref_count;
		_ptr=r1._ptr;
		(*_ref_count)++;
		return *this;
	}

	inline T* c_ptr()
	{
		return _ptr;
	}

	inline unsigned long num_ref()
	{
		return *_ref_count;
	}
};

#endif//REF_H
#include "ref-1.h"

class Foobar
{
    public:
        int x;
};

ref<Foobar> sample_manipulation(ref<Foobar> in)
{
    ref<Foobar> f=in;
    //....
    return f;
}

int main(void)
{
    ref<Foobar> *f1 = new ref<Foobar>;
    ref<Foobar> f2;
    f2 = sample_manipulation(*f1);
    return 0;
}

Thank you,

but there is still a problem (in fact i had tried to use two operator=)

if I change sample_manipulation, with, for example :

ref<Foobar> f2=in;
	ref<Foobar> f3;
	f3=f2;

I have the following error :

: error: ambiguous overload for 'operator=' in 'f3 = f2'

I may be dreaming, but it would by nice to be able to use my ref<> class a simple way, and be also able to do that kind of assignations

Do you think it is possible ?

Well when I assign one class to another I ussually just set the data from the one equal to the other via a void operator eg.

#include <iostream>

class foobar
{
    public:
        void operator =(const foobar &a)
        {
            this->x = a.x;
        }
        void setX(const int &x)
        {
            this->x = x;
        }
        const int& printX() const
        {
            return this->x;
        }
     private:
            int x;
};

int main()
{
    foobar f1;
    foobar f2;
    f1.setX(10);
    f2 = f1;
    std::cout<<f2.printX()<<std::endl;
    std::cin.get();
}

Yes, but for my particular problem ("minimalist incremental garbage collection") I have to change the reference count in both destination and source instance, because the content of the left side of the '=' "loses" a reference, and the right side "gains" a reference. (I use a reference counter to know when I really have to delete the owned pointer).

The ref<> class aims at automatically destroy the objects that do not have any references anymore (i.e that cannot be acceeded by the rest of the program) in order to avoid memory leaks.

In fact I think that I have to find another solution for my implementation, as it doesn't seem possible to have several signatures for operator= in the same class.
I don't think that i can write both

ref<Something> t1, t2;
t1=t2;

AND

ref<Something> myFunc();
....
t1=myFunc();

Quite bad... (f.....g c++ ! )

If you have an idea, that woul be great,
but I'm a bit discouraged, (I've tried to solve this problem for a long time)

It is all about the const :)

#ifndef REF_H
#define REF_H

template<typename T> class ref;

template<typename T1, typename T2>
ref<T1> ref_cast(ref<T2>& r2)
{
	return ref<T1>(static_cast<T1>(r2.c_ptr()), r2.num_ref()+1);
}

template<typename T>
class ref
{
	private :

	T* _ptr;
	unsigned long *_ref_count;

	public :

	inline explicit ref(T* ptr) : _ptr(ptr), _ref_count(new unsigned long)
	{
		*_ref_count=1;
	}

	inline ref() : _ptr(0), _ref_count(new unsigned long)
	{
		*_ref_count=0;
	}

	inline ref(const ref<T>& copied)
	{
		_ref_count=copied._ref_count;
		_ptr=copied._ptr;
		(*_ref_count)++;
	}


	inline ~ref()
	{
		*_ref_count-=*_ref_count?1:0;
		if(*_ref_count == 0)
		{
			delete _ref_count;
			delete _ptr;
		}
	}

	inline T* operator->()
	{
		return _ptr;
	}

	inline bool operator!()
	{
		return _ptr==0;
	}

	inline bool operator==(ref<T>& r1)
	{
		return *((T*)_ptr)==*((T*)r1._ptr);
	}

	inline bool operator!=(ref<T>& r1)
	{
		return *((T*)_ptr)!=*((T*)r1._ptr);
	}
    //removed my other suggestion because I am dumb and changed your original to this
	const inline ref<T>& operator=(ref<T>& r1)
	{
		*_ref_count-=*_ref_count?1:0;
		_ref_count=r1._ref_count;
		_ptr=r1._ptr;
		(*_ref_count)++;
		return *this;
	}
	//more goodies
    const inline ref<T>& operator=(const ref<T>& r1)
	{
		*_ref_count-=*_ref_count?1:0;
		_ref_count=r1._ref_count;
		_ptr=r1._ptr;
		(*_ref_count)++;
		return *this;
	}       	       
	inline T* c_ptr()
	{
		return _ptr;
	}

	inline unsigned long num_ref()
	{
		return *_ref_count;
	}
};

#endif//REF_H
#include "ref-1.h"

class Foobar
{
    public:
        int x;
};

ref<Foobar> sample_manipulation(ref<Foobar> in)
{
    ref<Foobar> f = in;
    ref<Foobar> f2;
    f2 = f;
    return f;
}

int main(void)
{
    ref<Foobar> *f1 = new ref<Foobar>;
    ref<Foobar> f2;
    f2 = sample_manipulation(*f1);
    return 0;
}

Oh and I hate _ before data names it annoys me ;)

Thanks for the great question and reply. One thing confused me here is, when you do
ref<Foobar> f2;
f2 is a reference of Foobar object? Or say it is a Foobar's reference, then how can I
access x of Foobar? f2.x or (*f2).x apparently won't work.

In fact, I called it 'reference' because I have no imagination.

The real name for this kind of classes is "smart pointer". it acts like a pointer, but automatically destroys the object when not needed any more. So, no need to determine when you have to call delete, etc...

You can access Foobar's members just by using the -> operator :

ref<Foobar> theFoobar;
ref<Foobar> theOtherFoobar=new Foobar;

theOtherFoobar->x=0xDEADBEEF; //works well

//but !!!
theFoobar->x; //will crash, because no instance is owned by the ref.

Here I put a clean version of the class, that I wrote today, with an html documentation.

Have some fun !

sorry i am dumb, figured it out. BTW how to delete one's own post?

f2.c_ptr()->x
f1->c_ptr()->x

Thanks for the reply, I mean when you declare

ref<Foobar> *f1 = new ref<Foobar>;

you can't access x directly with -> but have to call through the c_ptr()method.

Thanks for the reply, I mean when you declare

ref<Foobar> *f1 = new ref<Foobar>;

you can't access x directly with -> but have to call through the c_ptr()method.

You normally DO NOT have to make pointers on the ref<> itself.
no need to write

ref<Foobar> *f1 = new ref<Foobar>

but only

ref<Foobar> f1=new Foobar

(this magic is done by using the 'explicit' keyword before ref<>'s constructor.)

I put the c_ptr() method for the one that have to get back the pointer for using with functions from other libraries.

Theorically, with your example, you could write

ref<Foobar> *f1 = new ref<Foobar>;
(*f1)->x;

but as I said, it think it is useless.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.