Problems when giving default value for 'const auto_ptr &' argument

  • Thread starter Rein Anders Apeland
  • Start date
R

Rein Anders Apeland

Consider the following working code:



#include <memory>
#include <iostream>

void print_ptr( const std::auto_ptr< int > & thePtr =
std::auto_ptr< int >() )
{
std::cout << "Ptr address: " << thePtr.get() << std::endl;
}

int main()
{
std::auto_ptr< int > somePtr( new int );
print_ptr( somePtr );
print_ptr();
return 0;
}




Using GCC 3.3.4 it compiles without warning.

Using GCC 4.0.2 it gives the following errors:

foo.cpp: In function ‘int main()’:
foo.cpp:15: error: no matching function for call to
‘std::auto_ptr<int>::auto_ptr(std::auto_ptr<int>)’
/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../include/c
++/4.0.2/memory:349: note: candidates are:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr_ref<_Tp>) [with _Tp = int]
/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../include/c
++/4.0.2/memory:212: note:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp1>&) [with _Tp1 = int, _Tp
= int]
/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../include/c
++/4.0.2/memory:199: note:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp>&) [with _Tp = int]
foo.cpp:6: error: in passing argument 1 of ‘void print_ptr(const
std::auto_ptr<int>&)’



It appears that having a default value of 'std::auto_ptr<T>()' to
a parameter of type 'const std::auto_ptr<T> &' is not allowed in
GCC 4.0.2. Is there something in the C++ standard that is enforced in
4.0.2 and not in 3.3.4, or is it purely compiler-specific.

Does it have anything to do with the parameter being a reference?
 
K

Kanenas

Consider the following working code:

#include <memory>
#include <iostream>

void print_ptr( const std::auto_ptr< int > & thePtr =
std::auto_ptr< int >() )
{ [...]
print_ptr();
return 0;
}

Using GCC 3.3.4 it compiles without warning.

Using GCC 4.0.2 it gives the following errors:

foo.cpp: In function ‘int main()’:
foo.cpp:15: error: no matching function for call to
‘std::auto_ptr<int>::auto_ptr(std::auto_ptr<int>)’

I'm assuming line 15 is "print_ptr();".
/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../include/c
++/4.0.2/memory:349: note: candidates are:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr_ref<_Tp>) [with _Tp = int]
/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../include/c
++/4.0.2/memory:212: note:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp1>&) [with _Tp1 = int, _Tp
= int]
/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../include/c
++/4.0.2/memory:199: note:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp>&) [with _Tp = int]
foo.cpp:6: error: in passing argument 1 of ‘void print_ptr(const
std::auto_ptr<int>&)’



It appears that having a default value of 'std::auto_ptr<T>()' to
a parameter of type 'const std::auto_ptr<T> &' is not allowed in
GCC 4.0.2. Is there something in the C++ standard that is enforced in
4.0.2 and not in 3.3.4, or is it purely compiler-specific.
I'm reading an old standard, but it certainly allows temporaries to be
bound to references (section 12.2.5). I couldn't think of/find any
restrictions on using temporaries which would apply in this case. I
expect the responsibility lies with GCC 4.0.2.
Does it have anything to do with the parameter being a reference?

Based on the error message, no. It has to do with GCC not using
pass-by-reference semantics for the temporary when invoking
std::auto_ptr's (copy) constructor even though GCC could. As to why
GCC 4.0.2 is trying to pass the temporary to the constructor rather
than binding the reference to the temporary (as 3.3.4 does), I don't
know. Perhaps if GCC 4.0.2 would bind the temporary to a reference it
wouldn't be trying to invoke the constructor with the temporary during
thePtr's initialization.

If you're ever curious about a question of the form "Does it have
anything to do with x being y?", try changing x to something related
to y.
 
R

Rein Anders Apeland

Consider the following working code:

#include <memory>
#include <iostream>

void print_ptr( const std::auto_ptr< int > & thePtr =
std::auto_ptr< int >() )
{ [...]
print_ptr();
return 0;
}

Using GCC 3.3.4 it compiles without warning.

Using GCC 4.0.2 it gives the following errors:

foo.cpp: In function ‘int main()’:
foo.cpp:15: error: no matching function for call to
‘std::auto_ptr<int>::auto_ptr(std::auto_ptr<int>)’

I'm assuming line 15 is "print_ptr();".
/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../include/c
++/4.0.2/memory:349: note: candidates are:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr_ref<_Tp>) [with _Tp = int]
/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../include/c
++/4.0.2/memory:212: note:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp1>&) [with _Tp1 = int, _Tp
= int]
/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../include/c
++/4.0.2/memory:199: note:
std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp>&) [with _Tp = int]
foo.cpp:6: error: in passing argument 1 of ‘void print_ptr(const
std::auto_ptr<int>&)’



It appears that having a default value of 'std::auto_ptr<T>()' to
a parameter of type 'const std::auto_ptr<T> &' is not allowed in
GCC 4.0.2. Is there something in the C++ standard that is enforced in
4.0.2 and not in 3.3.4, or is it purely compiler-specific.
I'm reading an old standard, but it certainly allows temporaries to be
bound to references (section 12.2.5). I couldn't think of/find any
restrictions on using temporaries which would apply in this case. I
expect the responsibility lies with GCC 4.0.2.
Does it have anything to do with the parameter being a reference?

Based on the error message, no. It has to do with GCC not using
pass-by-reference semantics for the temporary when invoking
std::auto_ptr's (copy) constructor even though GCC could. As to why
GCC 4.0.2 is trying to pass the temporary to the constructor rather
than binding the reference to the temporary (as 3.3.4 does), I don't
know. Perhaps if GCC 4.0.2 would bind the temporary to a reference it
wouldn't be trying to invoke the constructor with the temporary during
thePtr's initialization.

In GCC 4.0.2, passing a temporary std::string() to a parameter of
type 'const std::string &' works fine. What could be the difference
between std::string and std::auto_ptr that triggers the error message?
 
P

Pete C

As to why
GCC 4.0.2 is trying to pass the temporary to the constructor rather
than binding the reference to the temporary (as 3.3.4 does), I don't
know.

When initialising a const reference to an rvalue (which we are in this
case), the compiler may either:

a) Bind the reference directly to the object that the rvalue
represents, or
b) Construct a temporary const object from the rvalue, and bind the
reference to the temporary.

The choice is implementation-defined, but the standard says that the
constructor that would be used in (b) must be available anyway.
However for auto_ptr, such a constructor is *not* available, because
auto_ptr's copy constructor takes a non-const reference (to which an
rvalue cannot be bound). So the new error is correct. See section
8.5.3.5 of the Standard for gory details.

Incidentally, the Microsoft implementation I'm currently looking at
(incorrectly) provides an auto_ptr which takes a const reference.
Plenty of code has been written that relies on this, sadly.

The difference with std::string (as questioned elsewhere on this
thread), is that std::string *does* provide a copy constructor from a
const reference - so (a) and (b) above are satisfied.
 
R

Rein Anders Apeland

When initialising a const reference to an rvalue (which we are in this
case), the compiler may either:

a) Bind the reference directly to the object that the rvalue
represents, or
b) Construct a temporary const object from the rvalue, and bind the
reference to the temporary.

The choice is implementation-defined, but the standard says that the
constructor that would be used in (b) must be available anyway.
However for auto_ptr, such a constructor is *not* available, because
auto_ptr's copy constructor takes a non-const reference (to which an
rvalue cannot be bound). So the new error is correct. See section
8.5.3.5 of the Standard for gory details.

Incidentally, the Microsoft implementation I'm currently looking at
(incorrectly) provides an auto_ptr which takes a const reference.
Plenty of code has been written that relies on this, sadly.

The difference with std::string (as questioned elsewhere on this
thread), is that std::string *does* provide a copy constructor from a
const reference - so (a) and (b) above are satisfied.

Thanks a lot! I now see why GCC 4.0.2 acts the way it does, and why
it must be that way.
 

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

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top