Re: Constraints on value type of iterators in two iterator ctors of sequences missing
===================================== MODERATOR'S COMMENT:
There seems to be a problem with the moderation
system; this message was approved when first submitted.
===================================== END OF MODERATOR'S COMMENT
[To the mods: I posted this answer more than two days ago,
but even after the receive message it did not came through.
So this is the attempt of a retrial]
James Kanze schrieb:
1. Shouldn't there be at least the requirement that the
iterator value type be convertible to the value type of the
container? As written, things like:
void * a[] = { &x, &y, &z } ;
std::string s( a, a + 3 ) ;
or:
class C {
C( int ) ;
} ;
C a[] = { C(1), C(2), C(3) } ;
std::string s( a, a + 3 ) ;
would not seem to be forbidden.
I strongly agree that the source items should be convertible
to those of the destination container. I also think that this is
currently not well expressed. IMO the sentence from 23.1.1/10
"[..] If there is no conversion from N to X::value_type, then this
is not a valid expression at all."
gives some evidence for this intent ;-). Also note that n2134 has
made this *sligthly* clearer in its corresponding paragraph:
"In the previous paragraph the alternative binding will fail if first
is not implicitly convertible to X::size_type or if last is not
implicitly convertible to X::value_type."
Both wordings seem *not* to unambigiously express this intent.
2. What is actually meant by "constructs a sequence equal to"?
Consider:
double d[] = { 3.14, -0.1 } ;
std::string s( d, d + 2 ) ;
Is this legal? If not, why not? But if so, if I read the
text na?vely, the implementation is required to ensure
that
std::equals( s.begin(), s.end(), d )
returns true, which is going to be more than just difficult.
I agree with that point.
I would propose the following modifications:
In [sequence.reqmts]:
1. In paragraph 3, the text concerning i and j be amended to
read:
i and j denote iterators of the same type satisfying
input iterator requirements, [i, j) denotes a valid
range, and the value type of i and j be implicitly
convertible to the value type of the container
Basically I think this is the right tone. Please note that
by means of concepts this is nicely expressed already
in
http://www2.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2085.pdf
page 8, 24.1.1/5:
concept Sequence<typename X> : Container<X>
{
...
X::X(size_type n, value_type t);
template<InputIterator Iter>
where Convertible<Iter::value_type, value_type>
X::X(Iter first, Iter last);
...
}
(Note that most recently "where" was changed to "requires")
and according to
http://www2.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2082.pdf
page 4, 20.1.8/1:
"Concept Convertible requires an implicit conversion from
one type to another.[..]"
2. In the entry concerning X(i, j) in table 82, the third
column be changed to:
post size() == distance between i and j
constructs a sequence such that each element of the
sequence is equal to the corresponding element of
the sequence [i, j), converted to the value type of
the container.
3. In the entries concerning a.insert(p,i,j) and
a.assign(i,j), the text "copies of elements in [i,j)" be
replaced by "elements equal to the elements which would
be present in X(i,j)".
This would match the current demands on == for the
containers itself. Personally I have some provisios for the
current meaning of EqualityComparable from table 28,
20.1.1, where we have
For all a, a == a.
Question: Do we have to interpret floating point types as
types not necessarily fulfilling EqualityComparable,
because in case of NaN values a == a might not succeed?
I tend to say that if
std::numeric_limits<T>::has_quiet_NaN ||
std::numeric_limits<T>::has_signaling_NaN
then EqualityComparable is not necessarily fulfilled for
T (e.g. T = double).
Even apart from floating point types we can think of an
user-defined type T which might not provide an equivalence
relation. Table 65 in 23.1 is not very enligthening, it just
says for a == b:
"==is an equivalence relation."
But for what? I read it to mean an equivalence relation for
the containers, but what if T does not fulfill this? Interestingly
the corresponding preconditions for a < b are clearer
expressed:
"pre: < is defined for values of T. < is a total ordering relation."
On the other side this description seems to have *another*
inconsistency: According to the definition of
LessThanComparable, 20.1.2, we only need to fulfill a
*strict weak ordering* relation. So why must < be here a
*total ordering*?
Of course this is another problem than you want to discuss,
but IMO it exists. If so, we cannot *unconditionally* require
the above demanded equality statement as post-condition
of a sequence assignment with another sequence, we can
*only* require it, if there exists a equivalence relation
between the source type and the destination type.
(inset: The concept paper
http://www2.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2082.pdf
fortunately defines EqualityComparable in a heterogenous way as
auto concept EqualityComparable<typename T, typename U = T>.)
So what do we do, if this requirement is not fulfilled? The only
fallback I see is similar to the chicken-and-egg problem of
CopyConstructible, which ends with the statement "t is equivalent
to T(t)" with whatever interpretation we give for equivalent ;-)
Astonishingly the concept proposal has removed this requirement
on CopyConstructible - an oversight?
Greetings from Bremen,
Daniel
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]