g++ "no matching function to call" using a template

V

Vaca Louca

Hello,

My setup: Debian sarge on dual Pentium 4. g++ 3.3.5-3.
(the other system is Windows XP with MS Visual Studio .NET 2003)

I have an auto_array<T> template (based on a template taken from the
Corona
project hosted at SourceForge) which basically wants to implement
std::auto_ptr<T>
semantics for an array.

It used to compile and run the test program I wrote for it but suddenly
it stopped
compiling and I have no idea what did I do wrong (or change at all).

On MS Visual Studio .NET 2003 the sample test program below (which I
clipped
down to demo the problem) compiles and runs find.

Here is the sample program:

#include <cstddef>
#include <cstring>

template<typename T>
class auto_array
{
public:
explicit auto_array (T* initial = 0) : array(initial) { }
auto_array(auto_array<T>& other) : array(other.release()) { }
~auto_array() { delete[] array; }
T* get() const { return array; }
T* release() { T* old = array; array = 0; return old; }
void reset(T* a = 0)
{
if (a != array) { delete[] array; array = a; }
}
void reset(auto_array<T>& a)
{
if (this != &a) { delete[] array; array = a.release(); }
}
auto_array<T> &operator= (T* a) { reset(a); return *this; }
auto_array<T> &operator= (auto_array<T>& a)
{
reset(a.release()); return *this;
}
private:
T* array;
};

auto_array<char> f(auto_array<char>& input) { return input; }

int main(int argc, char* argv[])
{
auto_array<char> a,b,c;
c.reset(a);
b = c;
// next two lines causes the errors
c.reset(f(b));
b = f(b);
}

The lines which cause the errors are the last two in main().

Could someone please tell where is my mistake? I can't find it myself
from digging the net or reading the books.

Thanks,

--Amos
 
C

Chris \( Val \)

| Hello,
|
| My setup: Debian sarge on dual Pentium 4. g++ 3.3.5-3.
| (the other system is Windows XP with MS Visual Studio .NET 2003)
|
| I have an auto_array<T> template (based on a template taken from the
| Corona
| project hosted at SourceForge) which basically wants to implement
| std::auto_ptr<T>
| semantics for an array.
|
| It used to compile and run the test program I wrote for it but suddenly
| it stopped
| compiling and I have no idea what did I do wrong (or change at all).

[snip]

I'm not sure whay you need this function, but instead of it...

| auto_array<char> f(auto_array<char>& input) { return input; }

[snip]

....change it to us a reference, and possibly even make it
a template function as well:

template<typename T>
auto_array<T>& f( auto_array<T>& input )
{
return input;
}

Cheers,
Chris Val
 
V

Vaca Louca

This function is used to test the function parameter passing and
return of a local instance of auto_array<T>, and to make sure the value
is copied correctly (and ownership is given up correctly).

Actually, the original test function is:

auto_array<char> f(auto_array<char>& input)
{
auto_array<char> local(input);
return local;
}

Since the function returns a local variable it can't return a
reference,
but must use pass-byt-value.
I just shortened the code as much as possible while still trying to
demonstrate the problem.

Thanks,

--A
 
V

Vaca Louca

Replying to myself (but maybe of benefit to others):

Apparently, the function return value (the one being return by f()
in my example) is considered "const", and therefore the operator=
and the copy constructor were not considered as candidates which
will accept this as an argument.
Once I made them accept const parameters (and override the
const using const_cast<> in order to actually reset the parameter's
values)the program passed compilation.

Here is the fixed program:

template<typename T>
class auto_array
{
public:
explicit auto_array (T* initial = 0) : array(initial) { }
auto_array(const auto_array<T>& a) : array(a.array)
{
if (this != &a)
{
const_cast<auto_array<T>*>(&a)->array = 0;
}
}
~auto_array() { delete[] array; }
T* get() const { return array; }
T* release() { T* old = array; array = 0; return old; }
void reset(T* a = 0)
{
if (a != array) { delete[] array; array = a; }
}
void reset(const auto_array<T>& a)
{
if (array != a.array) {
delete[] array;
array = const_cast<auto_array<T>*>(&a)->release();
}
}
auto_array<T> &operator= (T* a) { reset(a); return *this; }
auto_array<T>& operator= (const auto_array<T>& a)
{
reset(const_cast<auto_array<T>*>(&a)->release()); return *this;
}
private:
T* array;
};

auto_array<char> f(auto_array<char>& input) { return input; }

int main(int argc, char* argv[])
{
auto_array<char> a,b,c;
b.reset(a);
c = b;
// next lines used to cause the errors
c.reset(f(b)); // simple reset
c = f(b); // operator=
auto_array<char> d(f(c)); // copy constructor
}

I only wonder if people can comment whether this looks to them
as a good code. I'm a bit uneasy with all this const overriding
(I think I should be worried at the design level - laying to the
template's users about the constness of their objects).

Thanks,

--Amos
 
C

Chris \( Val \)

| This function is used to test the function parameter passing and
| return of a local instance of auto_array<T>, and to make sure the value
| is copied correctly (and ownership is given up correctly).
|
| Actually, the original test function is:
|
| auto_array<char> f(auto_array<char>& input)
| {
| auto_array<char> local(input);
| return local;
| }
|
| Since the function returns a local variable it can't return a
| reference, but must use pass-byt-value.

True, but you failed to mention that :)

| I just shortened the code as much as possible while still trying to
| demonstrate the problem.

Why not make the local instance 'static' ?

auto_array<char>& f( auto_array<char>& input )
{
static auto_array<char> local( input );
return local;
}

Then you can return by reference, and you do not need
to go breaking things with const_cast as you have in
your other post :)

Btw, where do you allocate memory ?

Cheers,
Chris Val
 
S

Samee Zahur

I found a rather easy hack into your problem ... just add this line as
a public member function:

operator auto_array<T>&(){return *this;}

It works with no complaints whatsoever!! (at least for gcc)

Hold it! I still haven't got a clue as to what's happenning here. When
returning an object by value, we do need a copy constructor, don't we?
But array_ptr hasn't got one! It even works if I declare a copy-ctor
myself and keep it in the *private* section! After experimenting a
little with this myself, I'm beginning to suspect that the move-ctor
symantecs have already been implemented in gcc (or I have been living
in the stone age!)

And as for the "no matching function" problem, the thing is gcc is a
little lazy when it comes to matching up template parameters - a ctor
needs a parameter of const T*, and it complains when it sees a call
passed with a simple T* - it doesn't see the match without a partial
specialization or something.
Apparently, the function return value (the one being return by f()
in my example) is considered "const",

I wouldn't agree - you might want to look up one of my recent threads
and what others had to say about it:

http://groups-beta.google.com/group/comp.lang.c++/browse_thread/thread/532943e5798f58db



Samee
 
V

Vaca Louca

I'm not sure what's happens with your operator overload either.

I assume by "array_ptr" you mean "auto_array"? It does have
a copy constructor.

As far as I know the language, a "const T" should accept a plain
"T", though not the toher way around.

I see the thread you are reffering to. Don't know what to say about it.

Thanks,

--Amos
 
V

Vaca Louca

STATIC??
It's not thread-safe to begin with, and I need to allocate variable
array size on top of this.
Memory allocation is done with "new char[buffer_size]" and is
used here just because Visual C++ 2003 .NET still doesn't
support local arrays with variable size, e.g.:

#ifdef _MSC_VER
auto_array<char> auto_key_buffer(new char[key_buffer_size]);
char *key_buffer(auto_key_buffer.get());
#else
char key_buffer[key_buffer_size];
#endif

I need this because I don't want to leak memory in case of an exception
or other unplanned function return.

Cheers,

--Amos
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top