question on list<int&>

S

subramanian100in

For vector and deque, the memory layout may be contiguous in which
case we cannot have array of references and so we cannot have
vector<int&> and deque<int&>. Am I correct?

However I am unable to create

list<int&> c;

Though 'list' does not involve contiguous memory layout, the above is
disallowed because we cannot reseat a reference(in the sense that we
cannot rebind a reference to a different object through assignment
operator). Is the reasoning correct; or is there some other reason for
disallowing list of references.

Kindly clarify.

Thanks
V.Subramanian
 
I

Ian Collins

For vector and deque, the memory layout may be contiguous in which
case we cannot have array of references and so we cannot have
vector<int&> and deque<int&>. Am I correct?
You can't have a container of references because references can't be
reseated or default initialised.
 
K

Kai-Uwe Bux

Ian said:
You can't have a container of references because references can't be
reseated or default initialised.

Actually, default constructibility is not a general requirement for
container value_types. It is only required for certain member functions
that sport a default argument T(). See [20.1.4].

Reseatability is not explicitly mentioned. However, reference types do not
satisfy the Assignable requirement since the return type would be a
reference to a reference. References also do not satisfy the
CopyConstructible requirements [20.1.3], e.g., if T is the type S&, and t
is a variable of type T, then &t will be of type S* not of type T*.
Admissible value_types for containers must satisfy the CopyConstructible
and Assignable requirements.

Practically, however, most implementations of container templates will
simply bail out when the container::reference typedef is defined and the
compiler is asked to form a reference to a reference.

In any case, contiguity of memory is completely unrelated.


Best

Kai-Uwe Bux
 
R

Ron Natalie

Ian said:
You can't have a container of references because references can't be
reseated or default initialised.
Neither of which is a requirement.

The issue is that the reference is not copy constructible NOR assignable.

There's no requirement that the types used in standard containers be
default constructible. They are always copy constructed.
 
I

Ian Collins

Ron said:
Neither of which is a requirement.

The issue is that the reference is not copy constructible NOR assignable.
Which amounts to reseating.
There's no requirement that the types used in standard containers be
default constructible. They are always copy constructed.
You forget <map>
 
K

Kai-Uwe Bux

Ian said:
Which amounts to reseating.

Nope. The Assignable concept for type T only requires that if a and b have
type T, the expression a = b has the type T& and the postcondition that a
is "equivalent" to b (think a == b). The reason Assignable fails for
reference types is that the return type does not match. The expression a =
b, however, is perfectly fine for reference types and does have the
required postcondition (without reseating).


[snip]

Best

Kai-Uwe Bux
 
J

James Kanze

Which amounts to reseating.

Or does it?

Ron's wrong in saying that references are not copy
constructible; they are. They're also assignable in the sense
that you can use = on an existing reference. The requirement
that they don't meet is Assignable: assignment of a reference
doesn't have the correct semantics (which should be basically
the same as those of copy construction).
You forget <map>

It's still only a requirement if you use operator[]. Most of
the time, you don't need it.

According to the current standard, CopyConstructible and
Assignable are absolute requirements: you can't instantiate the
class without them. A default constructor, on the other hand,
is only required if you instantiate (use) the specific functions
which use it. More like the < operator (required by
list<>::sort()).
 
J

James Kanze

Nope. The Assignable concept for type T only requires that if
a and b have type T, the expression a = b has the type T& and
the postcondition that a is "equivalent" to b (think a == b).

I don't think so. The standard is (intentionally) very vague on
what is meant by "equivalent", but it does make the requirement
of equivalence for both assignment and copy construction. And
while one can argue that either copy construction or assignment
results in equivalence in the case of references, it seems to me
that the exact meaning of equivalence is not the same in the two
cases. When you chose one for the definition you want to use in
specifying the concepts, you find that references don't
correctly implement the semantics of the other.
The reason Assignable fails for reference types is that the
return type does not match.

Because the return type would be a reference to a reference?
There's that, too.

The requirement concerning the return type of assignment
actually seems to be overspecification to me. It's certainly
not needed. On the other hand, although I don't see the
requirement specified as such, it seems pretty certain that you
must be able to create a reference to the type; I don't see how
else the implementation will be able to define
Container<>::reference. (That assumes you're using the standard
allocator, of course.) In practice, there are probably a number
of other problems involved with trying to make an implementation
work with references as well. (Think of the contiguity
constraints on std::vector.)

Perhaps the most fundamental reason why you cannot have a
container of references is the very first sentence of the
requirements section: "Containers are objects that store other
objects." A reference is not an object (nor is a function, or a
type, and you cannot have containers of functions nor of types,
either).
The expression a = b, however, is perfectly fine for reference
types and does have the required postcondition (without
reseating).

That depends on how you define the post-condition. If you
define it such that it works for assignment, then it fails for
copy constructors.

I think the most fundamental reason, however, is that a
reference is not an object, and containers can only store
objects.
 
J

James Kanze

Let me amend that to say "sequences" rather than containers.

Don't. I have instances of std::map in which the types don't
support default construction. The standard never requires
default construction in order to instantiate a container. It
only requires it if you use a specific function which requires
it. Exactly like < or == (and no one ever claims that standard
containers require < or ==).
 
K

Kai-Uwe Bux

James Kanze wrote many things I agree with and this:
I don't think so. The standard is (intentionally) very vague on
what is meant by "equivalent", but it does make the requirement
of equivalence for both assignment and copy construction. And
while one can argue that either copy construction or assignment
results in equivalence in the case of references, it seems to me
that the exact meaning of equivalence is not the same in the two
cases. When you chose one for the definition you want to use in
specifying the concepts, you find that references don't
correctly implement the semantics of the other.

Just for clarification: You mean that the postcondition after copy
construction

T & lhs ( rhs );

is &lhs == &rhs and after assignment

lhs = rhs

it is lhs == rhs?


That's a good point.



Best

Kai-Uwe Bux
 
J

James Kanze

James Kanze wrote many things I agree with and this:
Just for clarification: You mean that the postcondition after
copy construction
T & lhs ( rhs );
is &lhs == &rhs and after assignment
lhs = rhs
it is lhs == rhs?

More or less. (Of course, if &lhs == &rhs, then lhs == rhs.
Even if you modify one of them in the future:).) But I didn't
want to express it too much strictly in terms of ==, since that
might not even be implemented. The idea is just that the copy
constructor copies the reference, where as the assignment
operator copies the referred to object, and those are two
radically different semantics, which take a different view of
"copy" (and thus, of the "equivalence" of the results).

In the end, the standard says that containers are objects which
contain other objects, and references aren't objects. I don't
think you have to delve into the details of what is meant by
each required concept (which is necessarily vague when you start
talking about the equivalence of two objects after an operation)
to say that containers of references aren't supported.
 
I

Ian Collins

James said:
You forget <map>

It's still only a requirement if you use operator[]. Most of
the time, you don't need it.

According to the current standard, CopyConstructible and
Assignable are absolute requirements: you can't instantiate the
class without them. A default constructor, on the other hand,
is only required if you instantiate (use) the specific functions
which use it. More like the < operator (required by
list<>::sort()).
OK, thanks for the clarification James. I frequently use std::map as an
associative array, so I've always supplied a default constructor for
objects that end up in maps.
 

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,780
Messages
2,569,611
Members
45,276
Latest member
Sawatmakal

Latest Threads

Top