A reference to non-const to be bound to a temporary object

J

John Ky

Hello:

I'm not sure how to word this question properly, so I'll start by
listing the code I am having problems with:

int main()
{
std::vector<int> x;
x.swap(std::vector<int>());
return 0;
}

This is also not allowed:

std::vector<int> get()
{
return std::vector<int>();
}

int main()
{
std::vector<int> x;
x.swap(get());
return 0;
}


I was told on another newsgroup that the following code is
nonstandard C++. The reason being that "Standard C++
doesn't allow a reference to non-const to be bound to a
temporary object."

But being able to bind a reference to non-const to a temporary
object is useful for taking advantage of using a swap method.

I find it useful to be able to avoid this restriction because
it allows me to wrap resources that are expensive to create
and destroy into a class and then move it around while
minimising copying and guaranteeing exception safety by
using a swap function, all in a concise piece of code.

For instance if the Resource class wrapped an expensive
resource and the create static method creates the resource
while the open static method opens the resource:

// Resource interface:
Resource Resource::eek:pen(char *name);
Resource Resource::create(char *name);

// Some code:
Resource resource1;
Resource resource2;

resource1.swap(Resource::eek:pen("XYZ"));
resource2.swap(Resource::create("abc"));

I'm therefore interested in the motivation for this restriction and
if there is another way to do the same job just as efficiently.

-John
 
R

Rob Williscroft

John Ky wrote in
Hello:

I'm not sure how to word this question properly, so I'll start by
listing the code I am having problems with:

int main()
{
std::vector<int> x;
x.swap(std::vector<int>());

change to:

std::vector said:
return 0;
}

HTH.

Rob.
 
A

Andrey Tarasevich

John said:
...
I'm therefore interested in the motivation for this restriction and
if there is another way to do the same job just as efficiently.
...

Just do it other way around

std::vector<int> x;
std::vector<int>().swap(x);

or in your case

Resource resource1;
Resource resource2;

Resource::eek:pen("XYZ").swap(resource1);
Resource::create("abc").swap(resource2);
 
J

Jeff Schwab

John Ky wrote:

int main()
{
std::vector<int> x;
x.swap(std::vector<int>());
return 0;
}

I was told on another newsgroup that the following code is
nonstandard C++. The reason being that "Standard C++
doesn't allow a reference to non-const to be bound to a
temporary object."

But being able to bind a reference to non-const to a temporary
object is useful for taking advantage of using a swap method.

I'm therefore interested in the motivation for this restriction and
if there is another way to do the same job just as efficiently.

In this particular case, x.clear( ) is probably the most efficient and
concise option.
 
D

David Harmon

Do it this way:

std::vector<int>().swap(x);

The fact that one of those would work and the other not just points out
the sillyness of the rule against binding non-const references to
temporaries.
 
H

Howard Hinnant

tom_usenet said:
The rule isn't silly except in the exact type match case (of which
vector::swap is an example).

I would argue that there are cases when even an exact type match case
should not bind a temporary to a non-const reference:

std::deque<int> stuff...
std::advance(stuff.begin(), stuff.size()/2);

I sure am glad this call to advance doesn't compile.

That being said, there are times when you *do* want to bind a temporary
to a non-const reference (and swap is certainly one of those times).
The best person to decide when to bind a temp to a ref is the author of
the function in question. And it would even be useful to overload two
functions based on whether or not they were binding to an rvalue or
lvalue:

void foo(const A& a); // bind to lvalues
void foo(A&& a); // bind to rvalues (proposed)

This is exactly what the move proposal is about:

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1377.htm

I would love to see:

template <class T, class A>
void
vector<T, A>::swap(vector&& v);

which would then allow:

x.swap(std::vector<int>());

I also wouldn't mind seeing:

template <class T> void swap(T&, T&);
template <class T> void swap(T&&, T&);
template <class T> void swap(T&, T&&);

I.e. at most one of the arguments to swap can be a temporary.

But I recommend keeping std::advance just the way it is (at least with
respect to this issue) :)

template <class InputIterator, class Distance>
void
advance(InputIterator& i, Distance n);

-Howard
 
J

John Ky

The rule isn't silly except in the exact type match case (of which
vector::swap is an example).

The rule may not be silly, but error messages tend to be. Take gcc for
example:

ELPolicyInfo.cpp: In member function `ELPolicyInfo&
ELPolicyInfo::eek:perator=(const ELPolicyInfo&)':
ELPolicyInfo.cpp:136: no matching function for call to `ELPolicyInfo::swap(
const ELPolicyInfo&)'
ELPolicyInfo.cpp:125: candidates are: void ELPolicyInfo::swap(ELPolicyInfo&)

Granted that this is a compiler issue rather than a language issue, but it
would
be nice if there were also a user-friendliness standard for C++ compilers
that
compiler implementations could strive for.

-John
 

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,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top