This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
PR 8347 revisited
- From: Brad Spencer <spencer at infointeractive dot com>
- To: libstdc++ at gcc dot gnu dot org
- Date: Thu, 12 Dec 2002 10:15:15 -0400
- Subject: PR 8347 revisited
Hello. I mailed Paolo about some issues related to PR 8347 (failing
to construct std::string from an empty vector's begin/end), and they
led me to question the current logic that throws the "attempt to
create a string from null pointer" exception.
The current code for string's iterator-based constructor starts with
the following code:
basic_string(_InputIter __beg, _InputIter __end, const _Alloc& __a)
{
// ...
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refcopy();
// NB: Not required, but considered best practice.
if (__builtin_expect(__beg == _InIter(), 0))
__throw_logic_error("attempt to create string with null pointer");
I am worried that the __beg == _InIter() is invalid invalid for
iterators that are non-pointer types. It implies that
default-constructed iterators are non-dereferencable. My reading of
24.1 paragraph 5 seems to indicate that an _uninitialized_ iterator is
singular and thus not dereferencable. However, it does not say
whether or not a default-constructed iterator is singular. In 24.1.3
(table 74, "Forward iterator requirements"), there is a note that says
"X() might be singular", but it does not say that it _must_ be
singular.
I think that, barring some way to specialize it for pointers alone,
the entire check-and-throw statement might need to be removed. If
nothing else, the text of the exception is incorrect because __beg
might not be a pointer.
In other words, I don't think the standard prevents me from writing a
class that meets all the iterator requirements but whose
default-constructed instance _is_ dereferencable. In such a case,
perhaps the container is implicit; perhaps the iterator runs against
some system resource.
A separate issue that is only relevant if my suspicions are wrong is
that I believe there needs to be an additional check before the
exception can be thrown. Consider the case where __beg == __end, but
the string is being constructed with a different instance of the
allocator (i.e. __a != _Alloc()). Because of this, I think the
exception condition (if valid) would have to be:
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refcopy();
// NB: Not required, but considered best practice.
if (__builtin_expect(__beg == _InIter(), 0))
if (__builtin_expect(!(__beg == __end), 0))
__throw_logic_error("attempt to create string with null pointer
--
------------------------------------------------------------------
Brad Spencer - spencer@infointeractive.com - "It's quite nice..."
Systems Architect | InfoInterActive Corp. | A Canadian AOL Company