constructor overloading and new operator

Feb 16, 2010 at 6:45pm
hello,
i'd like to implement an memory management with a wrapper-reference class, that counts references. for that reason i implemented a reference class and for reasons of type-checking with a template.
to control the instantiations and the number of references i want to overload the constructor and the assignment operator.
however, i have trouble with my implementation

i wish to have a syntax like this:
1
2
3
4
reference<myClass> myRef = new myClass();
reference<myClass> myRef2 = myRef;
reference<myClass> myRef3;
myRef3 = myRef;

/*i know it looks like java/c# but originally it should be possible, because
operator new returns a void* and the constructor takes everything i define in its declaration (or should ...).

version1 shows i'm not totally wrong.
*/
in the following i added 3 versions of implementation only differing in details.
i'm really wondering about the compiler's behavior.
g++ --version
g++ (Ubuntu 4.4.1-4ubuntu9) 4.4.1

can you please help me to realize the syntax i'd like to have? i'm sure, i have an obviously semantic mistake, but i don't have s.o. to check this. i assume it's tunnel vision :)

or please explain, why it's not possible.
cheers,
sebastian

p.s. i also tried not to use the overloaded assignment-operators in the constructors, but the behavior was the same.
p.p.s. in version2 this works: reference<dummy> ref1(new dummy()); but not reference<dummy> ref1 = new dummy();

version1:
reference.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
template <typename T>
class reference{
private:
  T* tok;
public:
  reference();
  reference(T* tok);
  reference<T>& operator = (T* tok);
  reference<T>& operator = (reference<T>& ref);
};
template<typename T>
reference<T>::reference()
  :tok(0){}
template<typename T>
reference<T>::reference(T* tok){
  (*this) = tok;
}
template<typename T>
reference<T>& reference<T>::operator = (T* tok){
  this->tok = tok;
  return *this;
}
template<typename T>
reference<T>& reference<T>::operator = (reference<T>& ref){
  this->tok = ref.tok;
  return *this;
}


test.cpp:
reference<dummy> ref1 = new dummy();
g++:
everything works fine!

version 2:
reference.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename T>
class reference{
private:
  T* tok;
public:
  reference();
  reference(T* tok);
  reference(reference<T>& ref);	//  i added this to realize: reference<dummy> ref2 = ref;
  reference<T>& operator = (T* tok);
  reference<T>& operator = (reference<T>& ref);
};
template<typename T>
reference<T>::reference()
  :tok(0){}
template<typename T>
reference<T>::reference(T* tok){
  (*this) = tok;
}
template<typename T> // and the definition of the previous declaration
reference<T>::reference(reference<T>& ref){
  (*this) = ref;
}
...

test.cpp:
1
2
3
4
5
6
7
8
#include "reference.hpp"

class dummy{};

int main(int argc, char * argv[]){
  reference<dummy> ref1 = new dummy();
  return 0;
}

g++:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:6: error: no matching function for call to ‘reference<dummy>::reference(reference<dummy>)’
reference.hpp:20: note: candidates are: reference<T>::reference(reference<T>&) [with T = dummy]
reference.hpp:16: note:                 reference<T>::reference(T*) [with T = dummy]
reference.hpp:13: note:                 reference<T>::reference() [with T = dummy]

--> my thoughts:
1.)why does the constructor with the reference-argument, i added, influence the behavior of the originally code?
2.)okay let's have a constructor with the signature: reference(reference<T>)
test.cpp:
1
2
3
4
5
6
7
8
9
10
11
#include "reference.hpp"

class dummy{};

int main(int argc, char * argv[]){
  //reference<dummy> ref1 = new dummy();
  reference<dummy> ref1;
  ref1 = new dummy();

  return 0;
}

g++:
however this works!, because of the "operator = (T* tok)" method
version3:
reference.hpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename T>
class reference{
private:
  T* tok;
public:
  reference();
  reference(T* tok);
  reference(reference<T> ref);  // LINE 8: i changed the constructor to a non-reference type
  reference<T>& operator = (T* tok);
  reference<T>& operator = (reference<T>& ref);
};
template<typename T>
reference<T>::reference()
  :tok(0){}
template<typename T>
reference<T>::reference(T* tok){
  (*this) = tok;
}
template<typename T>
reference<T>::reference(reference<T> ref){
  (*this) = ref;
}
...

test.cpp:
1
2
3
reference<dummy> ref1 = new dummy();
  //reference<dummy> ref1;
  //ref1 = new dummy(); 

g++:
In file included from test.cpp:1:
reference.hpp:8: error: invalid constructor; you probably meant ‘reference<T> (const reference<T>&)’
reference.hpp:20: error: prototype for ‘reference<T>::reference(reference<T>)’ does not match any in class ‘reference<T>’
reference.hpp:16: error: candidates are: reference<T>::reference(T*)
reference.hpp:13: error:                 reference<T>::reference()

--> my thoughts:
1.)what does "reference.hpp:8: invalid ..." means? or where is the sense to restrict a cunstructor with a non-reference typed argument?
2.)why do i "probably mean 'reference<T>&'?!?
Feb 16, 2010 at 9:55pm
Are you trying to re-invent boost::shared_ptr?
Feb 16, 2010 at 10:15pm
i almost expected this question :)
and i had no exact look on boost:
however, one of the requirements for this task is "no dependencies on external libraries" for that reason, i try to implement a structure with smart pointer behavior on my own...
Are you trying to re-invent boost::shared_ptr?

so the answer could be: yes, but i'm not sure

i assume, that in the boost-lib will be another implementation, that will not help me along, but i'm going to have a look.

are there further suggestions?

cheers,
sebastian
Feb 16, 2010 at 10:31pm
I think the issue is that stuff like:

std::string stuff = "abc";
is the same as
std::string stuff("abc");

So doing it that way causes it to look at your constructors, and it can't find a match. Couldb't you just make constructors for all of those types?

EDIT: new does not return a void*, it returns pointer of whatever type you are making.
Last edited on Feb 16, 2010 at 10:33pm
Feb 17, 2010 at 1:12pm
well, i got it:
thanks for the hint firedraco!
1
2
3
4
5
6
7
  reference();
  reference(T* tok); 
  // to realize: reference<dummy> ref1 = new dummy();

  reference(const reference<T>& ref);	
  // and not "reference (reference<T>& ref);" to realize: reference<dummy> ref2 = ref2;
  ...

what i learned of this:
1.) a copy-constructor requires definitely a "const T&" as argument
2.) anyway the compiler violates when overloading the constructor with
1
2
3
4
5
6
7
class T{
  T(T* aT);
  // violates with:
  T(T& aT);
  // correct:
  T(const T& aT);
};

cheers,
Sebastian
Topic archived. No new replies allowed.