Topic: Proposal for std::sequence - Rev.2
Author: carrierandoperator@yahoo.co.uk
Date: Wed, 12 Jun 2013 23:58:41 -0700 (PDT)
Raw View
------=_Part_289_5764331.1371106721565
Content-Type: text/plain; charset=ISO-8859-1
This is the second iteration of the proposal for std::sequence. The first
can be found at:
https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/ECVE9Dq1vn0
..
A sequence is a primitive class which I have used for several years. It is
used to represent an array of one or more elements. The elements are
externally owned. The class may be implemented using a pointer and a size.
There are two primary variants:
- one which represents an array of mutable elements
- and another which represents an array of immutable elements.
It is implemented as a template which takes a single type parameter:
// May be used to represent an array of T. The elements it represents may
be modified.
template<class T>
class mutable_sequence {...};
// May be used to represent an array of T. The elements it represents may
not be modified.
template<class T>
class sequence {...};
The type is useful because multiple ways to represent an array and its
associated size exist, but there is not a particularly clean and safe way
to represent that as a singular type in the standard library (which also
dissociates the array from the object responsible for the array's lifetime).
Consequently, we pass arrays in many different ways:
size_t foo(const int* elements, size_t n);
size_t foo(const std::array<int, N>&);
size_t foo(const std::vector<int>&);
size_t foo(const std::vector<int,SomeSpecialAllocator>&);
template<typename TArbitraryContainer>
size_t foo(const TArbitraryContainer&) {
/* e.g. TArbitraryContainer must support subscripting and size() */
}
But there are problems in taking one of these approaches:
1. Derived types of different sizes may be passed more easily via
pointer. Sequences offer checked conversions.
2. Can enforce storage requirements to a specific container type.
Sequences do not specify storage; they abstract storage.
3. Can result in unnecessary object copying (e.g. when your
implementation uses std::array<>, but must pass std::vector<> or when
allocators do not match). Sequences erase the container/storage from the
client.
4. Can force an implementation to store their arrays using container
types specified by the interfaces they use (e.g. when copying arrays is
undesirable). Sequences erase the container/storage from the client.
5. Can result in unnecessary source duplication (e.g. when the interface
declares/supports multiple variants of the foo() above). Although there are
variants of sequences, this is greatly simplified using sequences because
it removes the container/storage from the array.
6. Can result in unnecessary errors, particularly when copying is
involved or when the size and elements are passed as separate parameters.
7. Often results in clients unnecessarily providing access to container
mutators. For example, foo(std::vector<int>&) can not only modify the
elements in the vector, but also resize or swap the vector. If foo() only
needs to alter the element values, then foo(std::mutable_sequence<int>)
offers all that is necessary.
8. And in the case of the template, a vector or array may be passed, but
that exposes the implementation. Exposing the implementation can be
prohibitive to programs which are loaded dynamically or are meant to be
private. Using the template where a sequence will suffice can also result
in unnecessary copying (e.g. for each type) when one definition is often
adequate. This often (not always) results in redundant work for the
compiler and linker, as well as larger binaries; i.e.
template<>foo(std::array<int,5>), template<>foo(std::array<int,12>),
template<>foo(std::vector<int>, and
template<>foo(std::vector<int,my_allocator>) may all be exported when a
template is used.
Because the storage/container could (and often should) logically be removed
from the interfaces, the problems sequences solve come up pretty often in
practice. Sequences attempt to reduce these types of issues using a compact
and performant implementation.
The sequence claims no ownership of the elements it provides, and it
provides no cleanup of the array (i.e. it is not a smart pointer and quite
similar to a reference). The array a sequence represents may refer to
storage on the stack, heap, or static storage.
The public interface of a sequence offers:
1. Several constructors. These constructors honor mutability (or
immutability), are type safe, and they perform (some) validation of their
parameters when the array passed as parameter is not the type declared in
the sequence's template parameter list. Once an array is represented as a
sequence, it can be easily converted to a related sequence (e.g. a
sequence<int> may be constructed from a mutable_sequence<int>). Due to the
number of variations, not every constructor will be listed here. Sequences
currently support construction from C arrays (of known size),
std::vector<>, std::array<>, and may also support cases where const may be
introduced. The implementation performs some basic parameter validation at
construction (e.g. so that a derived type of a greater size may not be
passed).
2. Member functions to query size and element count, similar to
std::array<>.
3. Element accessors (at(), op[], front(), back()), similar to
std::array<>.
4. iterators. begin() and end(), also similar to std::array<>.
5. Member functions to get a "slice" of a sequence. A slice is a
sub-sequence of a sequence. It may represent the entire sequence or a
portion of the sequence it was taken from, but not elements beyond the
bounds of the source sequence.
Requirements
1. The sequence's elements are naturally aligned and the elements must
not have stricter alignment.
2. sequence<void>, sequence<const void>, mutable_sequence<void>,
mutable_sequence<const void> et.al. are forbidden.
Because sequences are lightweight and easy to construct and copy, they
should often be passed by value. Because the size and pointer may not be
changed, they are often created where they are needed. Expanding their
scope by allowing the size and/or pointer to be modified make it easier to
introduce errors (e.g. dangling pointers). Therefore, the inability to
assign them is a design choice. This "restriction" is not a problem in
practice because they are simple to create.
Variants Worth Consideration:
1. template<class T, size_t N>class sequence_n. This variant represents
an array with a fixed number of immutable elements.
2. template<class T, size_t N>class mutable_sequence_n. This variant
represents an array with a fixed number of mutable elements.
3. class octet_sequence. Represents a sequence of octets. This type can
be used rather than sequence<char> to represent arbitrary data (e.g.
punned, unnaturally aligned, or serialized). This is primarily useful
because it can introduce type safety.
4. class mutable_octet_sequence. As octet_sequence, but having mutable
elements.
Voiced or Possible Concerns
1. I suspect some people would favor that the type will have the ability
to represent a null pointer and/or zero elements. This has not been a
problem for me. In fact, I've found it has led to much cleaner programs.
For example, the function which takes a parameter does not need to validate
that the sequence represents a valid array -- synonymous to passing a
reference rather than a pointer. When the need to pass zero exists, it is
often preferable to designate a separate function -- similar to how one
would clear() a std::vector instead of assigning it a new, default
constructed instance.
2. Some people would prefer the pointer and size to be modifiable. This
would allow a sequence to be shrunk from either end.
Similar Proposal
array_ref was proposed in January 2012:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3334.html. It
seems array_ref is no longer active, but string_ref is still active (now
presented in another document, and named string_view).
Sequences have some commonalities with array_ref:
1. They both aim to accomplish similar goals -- to abstract storage from
an array and to associate a pointer with an element count.
2. They are both simple types which can be implemented with a pointer
and size (or a pair of pointers), and are easy to copy and create.
The differences are:
1. Sequences provide support for both immutable elements and mutable
elements. array_ref supports only immutable elements. Note: LLVM's ArrayRef
also offers a mutable variant, but it was not present in the proposal.
2. array_ref is assignable and may be shrunk from either end, whereas
sequences are not assignable or resizable. This is by design. Sequences are
very cheap to create and slice.
3. An array_ref may represent an array of 0 elements, whereas sequences
represent one or more elements. This is also by design.
The document which proposed array_ref also proposes a type called
string_ref, which is now being proposed as string_view. A string_view
offers several string specific additions, so the string_view and sequence
types should be considered distinct because sequences perform no additional
functionality for strings.
Illustrative interfaces (type checking omitted):
/**
@brief represents mutable elements
*/
template <class TValue> class mutable_sequence {
typedef Detail::sequence_imp imp;
static_assert(!std::is_void<TValue>::value, "sequences do not represent
void types");
public:
typedef TValue value_type;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef typename Detail::implementation_defined_iterator<value_type>::type
iterator;
typedef typename
Detail::implementation_defined_const_iterator<value_type>::type
const_iterator;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
public:
mutable_sequence();
template <class Tp> mutable_sequence(Tp p, size_type n);
template <class Tp> mutable_sequence(Tp a, Tp b);
template <class Tp, size_t N> explicit mutable_sequence(Tp (&array)[N]);
template <class TVectorValue, class TAllocator>
mutable_sequence(std::vector<TVectorValue, TAllocator>& vec);
template <class TArrayValue, size_t N>
mutable_sequence(std::array<TArrayValue, N>& array);
template <class Tp> mutable_sequence(mutable_sequence<Tp>& p);
/* copy construction is enabled if the value type is const. otherwise, the
const would be lost. */
template <class Tp> mutable_sequence(const mutable_sequence<typename
std::enable_if<std::is_const<value_type>::value, Tp>::type>& p);
mutable_sequence(mutable_sequence<value_type>&&) = default;
mutable_sequence(const mutable_sequence<typename
std::remove_const<value_type>::type>&) = delete;
template <class Tp> mutable_sequence(const sequence<typename
std::enable_if<std::is_const<value_type>::value, Tp>::type>& p);
public:
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
const_iterator cbegin() const;
const_iterator cend() const;
const_reverse_iterator crbegin() const;
const_reverse_iterator crend() const;
public:
size_type size() const;
constexpr size_type max_size() const;
bool empty() const;
public:
reference operator[](size_type n);
const_reference operator[](size_type n) const;
reference at(size_type n);
const_reference at(size_type n) const;
reference front();
const_reference front() const;
reference back();
const_reference back() const;
value_type* data();
const value_type* data() const;
public:
/**
@return a new sequence containing the elements in the range [@a a...@a
b)
*/
sequence<value_type> slice(size_type a, size_type b) const;
mutable_sequence<value_type> slice(size_type a, size_type b);
/**
@return a new sequence containing the first @a n elements
*/
sequence<value_type> slice_first(size_type n) const;
mutable_sequence<value_type> slice_first(size_type n);
/**
@return a new sequence containing the last @a n elements
*/
sequence<value_type> slice_last(size_type n) const;
mutable_sequence<value_type> slice_last(size_type n);
/**
@return a new sequence pair. first = [0...@a i), second = [@a
i...this->size)
*/
std::pair<sequence<value_type>, sequence<value_type> > divide(size_type i)
const;
std::pair<mutable_sequence<value_type>, mutable_sequence<value_type> >
divide(size_type i);
private:
pointer const d_element;
const size_type d_size;
};
/**
@brief represents immutable elements
*/
template <class TValue> class sequence {
typedef Detail::sequence_imp imp;
static_assert(!std::is_void<TValue>::value, "sequences do not represent
void types");
public:
typedef TValue value_type;
typedef const value_type& const_reference;
typedef typename
Detail::implementation_defined_const_iterator<value_type>::type
const_iterator;
typedef const value_type* const_pointer;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
public:
sequence();
template <class Tp> sequence(Tp p, size_type n);
template <class Tp> sequence(Tp a, Tp b);
template <class Tp, size_t N> explicit sequence(Tp (&array)[N]);
template <class TVectorValue, class TAllocator> sequence(const
std::vector<TVectorValue, TAllocator>& vec);
template <class TArrayValue, size_t N> sequence(const
std::array<TArrayValue, N>& array);
sequence(sequence<value_type>&&) = default;
sequence(const sequence<value_type>&) = default;
template <class Tp> sequence(const sequence<Tp>& p);
template <class Tp> sequence(const mutable_sequence<Tp>& p);
public:
const_iterator begin() const;
const_iterator end() const;
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
const_iterator cbegin() const;
const_iterator cend() const;
const_reverse_iterator crbegin() const;
const_reverse_iterator crend() const;
public:
size_type size() const;
constexpr size_type max_size() const;
bool empty() const;
public:
const_reference operator[](size_type n) const;
const_reference at(size_type n) const;
const_reference front() const;
const_reference back() const;
const value_type* data() const;
public:
/**
@return a new sequence containing the elements in the range [@a a...@a
b)
*/
sequence<value_type> slice(size_type a, size_type b) const;
/**
@return a new sequence containing the first @a n elements
*/
sequence<value_type> slice_first(size_type n) const;
/**
@return a new sequence containing the last @a n elements
*/
sequence<value_type> slice_last(size_type n) const;
/**
@return a new sequence pair. first = [0...@a i), second = [@a
i...this->size)
*/
std::pair<sequence<value_type>, sequence<value_type> > divide(size_type i)
const;
private:
const_pointer const d_element;
const size_type d_size;
};
Note: This interface was developed and tested on one compiler, and it
differs from the source implementation. It's just an illustration drawn up
quickly, and would likely be improved over time.
I'd be interested to hear whether or not you think this would be a good
addition, how it can be improved, and what you like and/or dislike about it.
Thanks,
Justin Carlson
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_289_5764331.1371106721565
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">This is the second iteration of the proposal for std::=
sequence. The first can be found at: <a href=3D"https://groups.google.com/a=
/isocpp.org/forum/?fromgroups#!topic/std-proposals/ECVE9Dq1vn0">https://gro=
ups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/ECVE9Dq1=
vn0</a>.</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">A sequence is a primitive class which I have used for =
several years. It is used to represent an array of one or more elements. Th=
e elements are externally owned. The class may be implemented using a point=
er and a size.</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">There are two primary variants:</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; "><span class=3D"Apple-tab-span" style=3D"white-space:pr=
e"> </span>- one which represents an array of mutable elements</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; "><span class=3D"Apple-tab-span" style=3D"white-space:pr=
e"> </span>- and another which represents an array of immutable elements.</=
p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">It is implemented as a template which takes a single t=
ype parameter:</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<div style=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(1=
87, 187, 187); word-wrap: break-word; " class=3D"prettyprint"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #800;"=
class=3D"styled-by-prettify">// May be used to represent an array of T. Th=
e elements it represents may be modified.</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">template</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">class</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
<br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">class<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> mutable_se=
quence </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{..=
..};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <br><b=
r></span><span style=3D"color: #800;" class=3D"styled-by-prettify">// May b=
e used to represent an array of T. The elements it represents may not be mo=
dified. </span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r></span><span style=3D"color: #008;" class=3D"styled-by-prettify">template=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> <br></span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">class</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> sequence </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">{...};</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span></div></code></div><p style=3D"margin=
-bottom: 0px; font-size: 12px; line-height: normal; font-family: Helvetica;=
min-height: 14px; "><br><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">The type is useful because multiple ways to represent =
an array and its associated size exist, but there is not a particularly cle=
an and safe way to represent that as a singular type in the standard librar=
y (which also dissociates the array from the object responsible for the arr=
ay's lifetime).</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Consequently, we pass arrays in many different ways:</=
p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<div style=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(1=
87, 187, 187); word-wrap: break-word; " class=3D"prettyprint"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;"=
class=3D"styled-by-prettify">size_t foo</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">int</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
*</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> elements=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> size_t n</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">size_t foo</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">array</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify"><</span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">int</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> N</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">>&);</span></di=
v><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"style=
d-by-prettify">size_t foo</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">vector</span>=
<span style=3D"color: #080;" class=3D"styled-by-prettify"><int></span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">&);</span></=
div><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">size_t foo</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">const</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">vector</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">SomeSpecialAllocator</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">>&);</span></div><di=
v class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-=
prettify"></span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
<br>template</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
"><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">type=
name</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #606;" class=3D"styled-by-prettify">TArbitraryConta=
iner</span><span style=3D"color: #660;" class=3D"styled-by-prettify">></=
span></div><div class=3D"subprettyprint"><span style=3D"color: #000;" class=
=3D"styled-by-prettify">size_t foo</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">const</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify"=
>TArbitraryContainer</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">&)</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> </=
span><span style=3D"color: #800;" class=3D"styled-by-prettify">/* e.g. TArb=
itraryContainer must support subscripting and size() */</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> <br></span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span></div></code></div><p style=3D"=
margin-bottom: 0px; font-size: 12px; line-height: normal; font-family: Helv=
etica; min-height: 14px; "><br><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">But there are problems in taking one of these approach=
es:</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; "></p><ol><li><span style=3D"line-height: normal; ">Deri=
ved types of different sizes may be passed more easily via pointer. Sequenc=
es offer checked conversions.</span><br></li><li><span style=3D"line-height=
: normal; ">Can enforce storage requirements to a specific container type. =
Sequences do not specify storage; they abstract storage.</span><br></li><li=
><span style=3D"line-height: normal; ">Can result in unnecessary object cop=
ying (e.g. when your implementation uses std::array<>, but must pass =
std::vector<> or when allocators do not match). Sequences erase the c=
ontainer/storage from the client.</span></li><li><span style=3D"line-height=
: normal; ">Can force an implementation to store their arrays using contain=
er types specified by the interfaces they use (e.g. when copying arrays is =
undesirable). Sequences erase the container/storage from the client.</span>=
</li><li><span style=3D"line-height: normal; ">Can result in unnecessary so=
urce duplication (e.g. when the interface declares/supports multiple varian=
ts of the foo() above). Although there are variants of sequences, this is g=
reatly simplified using sequences because it removes the container/storage =
from the array.</span><br></li><li><span style=3D"line-height: normal; ">Ca=
n result in unnecessary errors, particularly when copying is involved or wh=
en the size and elements are passed as separate parameters.</span><br></li>=
<li><span style=3D"line-height: normal; ">Often results in clients unnecess=
arily providing access to container mutators. For example, foo(std::vector&=
lt;int>&) can not only modify the elements in the vector, but also r=
esize or swap the vector. If foo() only needs to alter the element values, =
then foo(std::mutable_sequence<int>) offers all that is necessary.</s=
pan><br></li><li><span style=3D"line-height: normal; ">And in the case of t=
he template, a vector or array may be passed, but that exposes the implemen=
tation. Exposing the implementation can be prohibitive to programs which ar=
e loaded dynamically or are meant to be private. Using the template where a=
sequence will suffice can also result in unnecessary copying (e.g. for eac=
h type) when one definition is often adequate. This often (not always) resu=
lts in redundant work for the compiler and linker, as well as larger binari=
es; i.e. template<>foo(std::array<int,5>), template<>foo(=
std::array<int,12>), template<>foo(std::vector<int>, and =
template<>foo(std::vector<int,my_allocator>) may all be exporte=
d when a template is used.</span><br></li></ol><p></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Because the storage/container could (and often should)=
logically be removed from the interfaces, the problems sequences solve com=
e up pretty often in practice. Sequences attempt to reduce these types of i=
ssues using a compact and performant implementation.</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">The sequence claims no ownership of the elements it pr=
ovides, and it provides no cleanup of the array (i.e. it is not a smart poi=
nter and quite similar to a reference). The array a sequence represents may=
refer to storage on the stack, heap, or static storage.</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">The public interface of a sequence offers:</p><p style=
=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-family: =
Helvetica; "></p><ol><li><span style=3D"line-height: normal; ">Several cons=
tructors. These constructors honor mutability (or immutability), are type s=
afe, and they perform (some) validation of their parameters when the array =
passed as parameter is not the type declared in the sequence's template par=
ameter list. Once an array is represented as a sequence, it can be easily c=
onverted to a related sequence (e.g. a sequence<int> may be construct=
ed from a mutable_sequence<int>). Due to the number of variations, no=
t every constructor will be listed here. Sequences currently support constr=
uction from C arrays (of known size), std::vector<>, std::array<&g=
t;, and may also support cases where const may be introduced. The implement=
ation performs some basic parameter validation at construction (e.g. so tha=
t a derived type of a greater size may not be passed).</span></li><li><span=
style=3D"line-height: normal; ">Member functions to query size and element=
count, similar to std::array<>.</span><br></li><li><span style=3D"li=
ne-height: normal; ">Element accessors (at(), op[], front(), back()), simil=
ar to std::array<>.</span><br></li><li><span style=3D"line-height: no=
rmal; ">iterators. begin() and end(), also similar to std::array<>.</=
span><br></li><li><span style=3D"line-height: normal; ">Member functions to=
get a "slice" of a sequence. A slice is a sub-sequence of a sequence. It m=
ay represent the entire sequence or a portion of the sequence it was taken =
from, but not elements beyond the bounds of the source sequence.</span><br>=
</li></ol><p></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Requirements</p><p style=3D"margin-bottom: 0px; font-s=
ize: 12px; line-height: normal; font-family: Helvetica; "></p><ol><li><span=
style=3D"line-height: normal; ">The sequence's elements are naturally alig=
ned and the elements must not have stricter alignment.</span></li><li><span=
style=3D"line-height: normal; ">sequence<void>, sequence<const vo=
id>, mutable_sequence<void>, mutable_sequence<const void> et=
..al. are forbidden.</span><br></li></ol><p></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Because sequences are lightweight and easy to construc=
t and copy, they should often be passed by value. Because the size and poin=
ter may not be changed, they are often created where they are needed. Expan=
ding their scope by allowing the size and/or pointer to be modified make it=
easier to introduce errors (e.g. dangling pointers). Therefore, the inabil=
ity to assign them is a design choice. This "restriction" is not a problem =
in practice because they are simple to create.</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Variants Worth Consideration:</p><p style=3D"margin-bo=
ttom: 0px; font-size: 12px; line-height: normal; font-family: Helvetica; ">=
</p><ol><li><span style=3D"line-height: normal; ">template<class T, size=
_t N>class sequence_n. This variant represents an array with a fixed num=
ber of immutable elements.</span></li><li><span style=3D"line-height: norma=
l; ">template<class T, size_t N>class mutable_sequence_n. This varian=
t represents an array with a fixed number of mutable elements.</span><br></=
li><li><span style=3D"line-height: normal; ">class octet_sequence. Represen=
ts a sequence of octets. This type can be used rather than sequence<char=
> to represent arbitrary data (e.g. punned, unnaturally aligned, or seri=
alized). This is primarily useful because it can introduce type safety.</sp=
an><br></li><li><span style=3D"line-height: normal; ">class mutable_octet_s=
equence. As octet_sequence, but having mutable elements.</span><br></li></o=
l><p></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Voiced or Possible Concerns</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "></p><ol><li><span style=3D"line-heig=
ht: normal; ">I suspect some people would favor that the type will have the=
ability to represent a null pointer and/or zero elements. This has not bee=
n a problem for me. In fact, I've found it has led to much cleaner programs=
.. For example, the function which takes a parameter does not need to valida=
te that the sequence represents a valid array -- synonymous to passing a re=
ference rather than a pointer. When the need to pass zero exists, it is oft=
en preferable to designate a separate function -- similar to how one would =
clear() a std::vector instead of assigning it a new, default constructed in=
stance.</span><br></li><li><span style=3D"line-height: normal; ">Some peopl=
e would prefer the pointer and size to be modifiable. This would allow a se=
quence to be shrunk from either end.</span><br></li></ol><p></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Similar Proposal</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">array_ref was proposed in January 2012: <a href=3D"htt=
p://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3334.html">http://www=
..open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3334.html</a>. It seems arra=
y_ref is no longer active, but string_ref is still active (now presented in=
another document, and named string_view).</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Sequences have some commonalities with array_ref:</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; "></p><ol><li><span style=3D"line-height: normal; ">They=
both aim to accomplish similar goals -- to abstract storage from an array =
and to associate a pointer with an element count.</span><br></li><li><span =
style=3D"line-height: normal; ">They are both simple types which can be imp=
lemented with a pointer and size (or a pair of pointers), and are easy to c=
opy and create.</span><br></li></ol><p></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">The differences are:</p><p style=3D"margin-bottom: 0px=
; font-size: 12px; line-height: normal; font-family: Helvetica; "></p><ol><=
li><span style=3D"line-height: normal; ">Sequences provide support for both=
immutable elements and mutable elements. array_ref supports only immutable=
elements. Note: LLVM's ArrayRef also offers a mutable variant, but it was =
not present in the proposal.</span><br></li><li><span style=3D"line-height:=
normal; ">array_ref is assignable and may be shrunk from either end, where=
as sequences are not assignable or resizable. This is by design. Sequences =
are very cheap to create and slice.</span><br></li><li><span style=3D"line-=
height: normal; ">An array_ref may represent an array of 0 elements, wherea=
s sequences represent one or more elements. This is also by design.</span><=
br></li></ol><p></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">The document which proposed array_ref also proposes a =
type called string_ref, which is now being proposed as string_view. A strin=
g_view offers several string specific additions, so the string_view and seq=
uence types should be considered distinct because sequences perform no addi=
tional functionality for strings.</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Illustrative interfaces (type checking omitted):</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p><p style=3D"margin-bottom: 0=
px; font-size: 12px; line-height: normal; font-family: Helvetica; min-heigh=
t: 14px; "><br></p>
<div style=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(1=
87, 187, 187); word-wrap: break-word; " class=3D"prettyprint"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><div class=3D"subprettyprint=
">/**</div><div class=3D"subprettyprint"> @brief represents mut=
able elements</div><div class=3D"subprettyprint"> */</div><div class=
=3D"subprettyprint">template <class TValue> class mutable_sequence {<=
/div><div class=3D"subprettyprint"> typedef Detail::sequence_imp imp;<=
/div><div class=3D"subprettyprint"> static_assert(!std::is_void<TVa=
lue>::value, "sequences do not represent void types");</div><div class=
=3D"subprettyprint"><br></div><div class=3D"subprettyprint">public:</div><d=
iv class=3D"subprettyprint"> typedef TValue value_type;</div><div clas=
s=3D"subprettyprint"> typedef value_type& reference;</div><div cla=
ss=3D"subprettyprint"> typedef const value_type& const_reference;<=
/div><div class=3D"subprettyprint"> typedef typename Detail::implement=
ation_defined_iterator<value_type>::type iterator;</div><div class=3D=
"subprettyprint"> typedef typename Detail::implementation_defined_cons=
t_iterator<value_type>::type const_iterator;</div><div class=3D"subpr=
ettyprint"> typedef value_type* pointer;</div><div class=3D"subprettyp=
rint"> typedef const value_type* const_pointer;</div><div class=3D"sub=
prettyprint"> typedef size_t size_type;</div><div class=3D"subprettypr=
int"> typedef ptrdiff_t difference_type;</div><div class=3D"subprettyp=
rint"> typedef std::reverse_iterator<iterator> reverse_iterator;=
</div><div class=3D"subprettyprint"> typedef std::reverse_iterator<=
const_iterator> const_reverse_iterator;</div><div class=3D"subprettyprin=
t"><br></div><div class=3D"subprettyprint">public:</div><div class=3D"subpr=
ettyprint"> mutable_sequence();</div><div class=3D"subprettyprint">&nb=
sp;template <class Tp> mutable_sequence(Tp p, size_type n);</div><div=
class=3D"subprettyprint"> template <class Tp> mutable_sequence(=
Tp a, Tp b);</div><div class=3D"subprettyprint"> template <class Tp=
, size_t N> explicit mutable_sequence(Tp (&array)[N]);</div><div cla=
ss=3D"subprettyprint"> template <class TVectorValue, class TAllocat=
or> mutable_sequence(std::vector<TVectorValue, TAllocator>& ve=
c);</div><div class=3D"subprettyprint"> template <class TArrayValue=
, size_t N> mutable_sequence(std::array<TArrayValue, N>& array=
);</div><div class=3D"subprettyprint"> template <class Tp> mutab=
le_sequence(mutable_sequence<Tp>& p);</div><div class=3D"subprett=
yprint"> /* copy construction is enabled if the value type is const. o=
therwise, the const would be lost. */</div><div class=3D"subprettyprint">&n=
bsp;template <class Tp> mutable_sequence(const mutable_sequence<ty=
pename std::enable_if<std::is_const<value_type>::value, Tp>::ty=
pe>& p);</div><div class=3D"subprettyprint"> mutable_sequence(m=
utable_sequence<value_type>&&) =3D default;</div><div class=
=3D"subprettyprint"> mutable_sequence(const mutable_sequence<typena=
me std::remove_const<value_type>::type>&) =3D delete;</div><di=
v class=3D"subprettyprint"> template <class Tp> mutable_sequence=
(const sequence<typename std::enable_if<std::is_const<value_type&g=
t;::value, Tp>::type>& p);</div><div class=3D"subprettyprint"><br=
></div><div class=3D"subprettyprint">public:</div><div class=3D"subprettypr=
int"> iterator begin();</div><div class=3D"subprettyprint"> const=
_iterator begin() const;</div><div class=3D"subprettyprint"> iterator =
end();</div><div class=3D"subprettyprint"> const_iterator end() const;=
</div><div class=3D"subprettyprint"> reverse_iterator rbegin();</div><=
div class=3D"subprettyprint"> const_reverse_iterator rbegin() const;</=
div><div class=3D"subprettyprint"> reverse_iterator rend();</div><div =
class=3D"subprettyprint"> const_reverse_iterator rend() const;</div><d=
iv class=3D"subprettyprint"> const_iterator cbegin() const;</div><div =
class=3D"subprettyprint"> const_iterator cend() const;</div><div class=
=3D"subprettyprint"> const_reverse_iterator crbegin() const;</div><div=
class=3D"subprettyprint"> const_reverse_iterator crend() const;</div>=
<div class=3D"subprettyprint"><br></div><div class=3D"subprettyprint">publi=
c:</div><div class=3D"subprettyprint"> size_type size() const;</div><d=
iv class=3D"subprettyprint"> constexpr size_type max_size() const;</di=
v><div class=3D"subprettyprint"> bool empty() const;</div><div class=
=3D"subprettyprint"><br></div><div class=3D"subprettyprint">public:</div><d=
iv class=3D"subprettyprint"> reference operator[](size_type n);</div><=
div class=3D"subprettyprint"> const_reference operator[](size_type n) =
const;</div><div class=3D"subprettyprint"> reference at(size_type n);<=
/div><div class=3D"subprettyprint"> const_reference at(size_type n) co=
nst;</div><div class=3D"subprettyprint"> reference front();</div><div =
class=3D"subprettyprint"> const_reference front() const;</div><div cla=
ss=3D"subprettyprint"> reference back();</div><div class=3D"subprettyp=
rint"> const_reference back() const;</div><div class=3D"subprettyprint=
"> value_type* data();</div><div class=3D"subprettyprint"> const =
value_type* data() const;</div><div class=3D"subprettyprint"><br></div><div=
class=3D"subprettyprint">public:</div><div class=3D"subprettyprint"> =
/**</div><div class=3D"subprettyprint"> @return a new sequence=
containing the elements in the range [@a a...@a b)</div><div class=3D"subp=
rettyprint"> */</div><div class=3D"subprettyprint"> sequence<=
value_type> slice(size_type a, size_type b) const;</div><div class=3D"su=
bprettyprint"> mutable_sequence<value_type> slice(size_type a, s=
ize_type b);</div><div class=3D"subprettyprint"> /**</div><div class=
=3D"subprettyprint"> @return a new sequence containing the fir=
st @a n elements</div><div class=3D"subprettyprint"> */</div><div cla=
ss=3D"subprettyprint"> sequence<value_type> slice_first(size_typ=
e n) const;</div><div class=3D"subprettyprint"> mutable_sequence<va=
lue_type> slice_first(size_type n);</div><div class=3D"subprettyprint">&=
nbsp;/**</div><div class=3D"subprettyprint"> @return a new seq=
uence containing the last @a n elements</div><div class=3D"subprettyprint">=
*/</div><div class=3D"subprettyprint"> sequence<value_type&g=
t; slice_last(size_type n) const;</div><div class=3D"subprettyprint"> =
mutable_sequence<value_type> slice_last(size_type n);</div><div class=
=3D"subprettyprint"> /**</div><div class=3D"subprettyprint"> &nb=
sp; @return a new sequence pair. first =3D [0...@a i), second =3D [@a i...t=
his->size)</div><div class=3D"subprettyprint"> */</div><div class=
=3D"subprettyprint"> std::pair<sequence<value_type>, sequence=
<value_type> > divide(size_type i) const;</div><div class=3D"subpr=
ettyprint"> std::pair<mutable_sequence<value_type>, mutable_s=
equence<value_type> > divide(size_type i);</div><div class=3D"subp=
rettyprint"><br></div><div class=3D"subprettyprint">private:</div><div clas=
s=3D"subprettyprint"> pointer const d_element;</div><div class=3D"subp=
rettyprint"> const size_type d_size;</div><div class=3D"subprettyprint=
">};</div><div class=3D"subprettyprint"><br></div><div class=3D"subprettypr=
int">/**</div><div class=3D"subprettyprint"> @brief represents =
immutable elements</div><div class=3D"subprettyprint"> */</div><div cl=
ass=3D"subprettyprint">template <class TValue> class sequence {</div>=
<div class=3D"subprettyprint"> typedef Detail::sequence_imp imp;</div>=
<div class=3D"subprettyprint"> static_assert(!std::is_void<TValue&g=
t;::value, "sequences do not represent void types");</div><div class=3D"sub=
prettyprint"><br></div><div class=3D"subprettyprint">public:</div><div clas=
s=3D"subprettyprint"> typedef TValue value_type;</div><div class=3D"su=
bprettyprint"> typedef const value_type& const_reference;</div><di=
v class=3D"subprettyprint"> typedef typename Detail::implementation_de=
fined_const_iterator<value_type>::type const_iterator;</div><div clas=
s=3D"subprettyprint"> typedef const value_type* const_pointer;</div><d=
iv class=3D"subprettyprint"> typedef size_t size_type;</div><div class=
=3D"subprettyprint"> typedef ptrdiff_t difference_type;</div><div clas=
s=3D"subprettyprint"> typedef std::reverse_iterator<const_iterator&=
gt; const_reverse_iterator;</div><div class=3D"subprettyprint"><br></div><d=
iv class=3D"subprettyprint">public:</div><div class=3D"subprettyprint">&nbs=
p;sequence();</div><div class=3D"subprettyprint"> template <class T=
p> sequence(Tp p, size_type n);</div><div class=3D"subprettyprint"> =
;template <class Tp> sequence(Tp a, Tp b);</div><div class=3D"subpret=
typrint"> template <class Tp, size_t N> explicit sequence(Tp (&a=
mp;array)[N]);</div><div class=3D"subprettyprint"> template <class =
TVectorValue, class TAllocator> sequence(const std::vector<TVectorVal=
ue, TAllocator>& vec);</div><div class=3D"subprettyprint"> temp=
late <class TArrayValue, size_t N> sequence(const std::array<TArra=
yValue, N>& array);</div><div class=3D"subprettyprint"> sequenc=
e(sequence<value_type>&&) =3D default;</div><div class=3D"sub=
prettyprint"> sequence(const sequence<value_type>&) =3D defa=
ult;</div><div class=3D"subprettyprint"> template <class Tp> seq=
uence(const sequence<Tp>& p);</div><div class=3D"subprettyprint">=
template <class Tp> sequence(const mutable_sequence<Tp>&a=
mp; p);</div><div class=3D"subprettyprint"><br></div><div class=3D"subprett=
yprint">public:</div><div class=3D"subprettyprint"> const_iterator beg=
in() const;</div><div class=3D"subprettyprint"> const_iterator end() c=
onst;</div><div class=3D"subprettyprint"> const_reverse_iterator rbegi=
n() const;</div><div class=3D"subprettyprint"> const_reverse_iterator =
rend() const;</div><div class=3D"subprettyprint"> const_iterator cbegi=
n() const;</div><div class=3D"subprettyprint"> const_iterator cend() c=
onst;</div><div class=3D"subprettyprint"> const_reverse_iterator crbeg=
in() const;</div><div class=3D"subprettyprint"> const_reverse_iterator=
crend() const;</div><div class=3D"subprettyprint"><br></div><div class=3D"=
subprettyprint">public:</div><div class=3D"subprettyprint"> size_type =
size() const;</div><div class=3D"subprettyprint"> constexpr size_type =
max_size() const;</div><div class=3D"subprettyprint"> bool empty() con=
st;</div><div class=3D"subprettyprint"><br></div><div class=3D"subprettypri=
nt">public:</div><div class=3D"subprettyprint"> const_reference operat=
or[](size_type n) const;</div><div class=3D"subprettyprint"> const_ref=
erence at(size_type n) const;</div><div class=3D"subprettyprint"> cons=
t_reference front() const;</div><div class=3D"subprettyprint"> const_r=
eference back() const;</div><div class=3D"subprettyprint"> const value=
_type* data() const;</div><div class=3D"subprettyprint"><br></div><div clas=
s=3D"subprettyprint">public:</div><div class=3D"subprettyprint"> /**</=
div><div class=3D"subprettyprint"> @return a new sequence cont=
aining the elements in the range [@a a...@a b)</div><div class=3D"subpretty=
print"> */</div><div class=3D"subprettyprint"> sequence<value=
_type> slice(size_type a, size_type b) const;</div><div class=3D"subpret=
typrint"> /**</div><div class=3D"subprettyprint"> @return=
a new sequence containing the first @a n elements</div><div class=3D"subpr=
ettyprint"> */</div><div class=3D"subprettyprint"> sequence<v=
alue_type> slice_first(size_type n) const;</div><div class=3D"subprettyp=
rint"> /**</div><div class=3D"subprettyprint"> @return a =
new sequence containing the last @a n elements</div><div class=3D"subpretty=
print"> */</div><div class=3D"subprettyprint"> sequence<value=
_type> slice_last(size_type n) const;</div><div class=3D"subprettyprint"=
> /**</div><div class=3D"subprettyprint"> @return a new s=
equence pair. first =3D [0...@a i), second =3D [@a i...this->size)</div>=
<div class=3D"subprettyprint"> */</div><div class=3D"subprettyprint">=
std::pair<sequence<value_type>, sequence<value_type> &=
gt; divide(size_type i) const;</div><div class=3D"subprettyprint"><br></div=
><div class=3D"subprettyprint">private:</div><div class=3D"subprettyprint">=
const_pointer const d_element;</div><div class=3D"subprettyprint">&nb=
sp;const size_type d_size;</div><div class=3D"subprettyprint">};</div><div>=
<br></div></div></code></div><br><br><p style=3D"margin-bottom: 0px; font-s=
ize: 12px; line-height: normal; font-family: Helvetica; min-height: 14px; "=
>Note: This interface was developed and tested on one compiler, and it diff=
ers from the source implementation. It's just an illustration drawn up quic=
kly, and would likely be improved over time.<br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">I'd be interested to hear whether or not you think thi=
s would be a good addition, how it can be improved, and what you like and/o=
r dislike about it.</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Thanks,</p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; min-height: 14px; "><br></p>
<p style=3D"margin-bottom: 0px; font-size: 12px; line-height: normal; font-=
family: Helvetica; ">Justin Carlson</p><p style=3D"margin-bottom: 0px; font=
-size: 12px; line-height: normal; font-family: Helvetica; "><br></p>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/?hl=3Den">http://groups.google.com/a/isocpp.org/group/std-pro=
posals/?hl=3Den</a>.<br />
<br />
<br />
------=_Part_289_5764331.1371106721565--
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Thu, 13 Jun 2013 10:09:01 -0700 (PDT)
Raw View
------=_Part_14_21390242.1371143341033
Content-Type: text/plain; charset=ISO-8859-1
What's the diff with r1?
I'd still go for a (iterator) range concept instead of a 'sequence' concept.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en.
------=_Part_14_21390242.1371143341033
Content-Type: text/html; charset=ISO-8859-1
What's the diff with r1?<div><br></div><div>I'd still go for a (iterator) range concept instead of a 'sequence' concept.</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en">http://groups.google.com/a/isocpp.org/group/std-proposals/?hl=en</a>.<br />
<br />
<br />
------=_Part_14_21390242.1371143341033--
.
Author: carrierandoperator@yahoo.co.uk
Date: Thu, 13 Jun 2013 10:54:52 -0700 (PDT)
Raw View
------=_Part_35_9087686.1371146092304
Content-Type: text/plain; charset=ISO-8859-1
The concept is the same as initially proposed, but the initial topic was a
rather informal query. I've provided more details and added some feedback
from the first.
Thanks
On Thursday, June 13, 2013 1:09:01 PM UTC-4, Olaf van der Spek wrote:
>
> What's the diff with r1?
>
> I'd still go for a (iterator) range concept instead of a 'sequence'
> concept.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_35_9087686.1371146092304
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
The concept is the same as initially proposed, but the initial topic was a =
rather informal query. I've provided more details and added some feedback f=
rom the first.<div><br></div><div>Thanks<br><br>On Thursday, June 13, 2013 =
1:09:01 PM UTC-4, Olaf van der Spek wrote:<blockquote class=3D"gmail_quote"=
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-=
left: 1ex;">What's the diff with r1?<div><br></div><div>I'd still go for a =
(iterator) range concept instead of a 'sequence' concept.</div></blockquote=
></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_35_9087686.1371146092304--
.
Author: carrierandoperator@yahoo.co.uk
Date: Thu, 13 Jun 2013 11:58:18 -0700 (PDT)
Raw View
------=_Part_107_1700322.1371149898026
Content-Type: text/plain; charset=ISO-8859-1
On Thursday, June 13, 2013 1:09:01 PM UTC-4, Olaf van der Spek wrote:
>
> I'd still go for a (iterator) range concept instead of a 'sequence'
> concept.
>
Questions on my mind: What is the status of Ranges? Is there a current
proposal that people are agreeing on? Is it being improved and does it have
open consideration for standardization in its current form? Is it based on
Boost?
I've found a (quiet) mailing list: http://www.open-std.org/pipermail/ranges/
I also ran across a document by Jeffrey Yasskin from jan.2012:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html
As well as some mentions in the lists.
If ranges are coming along well, there is likely one source I can go to
which would answer all these questions. Unfortunately, I cannot find that.
Sorry - I am new here =\
Prior to reviewing the range proposal: A range implementation could be made
to be significantly more complex than a representation of contiguous
elements (sequence). If the range proposal exists and happens to be
complex, then it might generally be regarded as a distinct type which is
aimed at solving a different problem.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_107_1700322.1371149898026
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Thursday, June 13, 2013 1:09:01 PM UTC-4, Olaf van der Spek wrote:<block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div>I'd still go for a (iterator) r=
ange concept instead of a 'sequence' concept.<br></div></blockquote><div><b=
r></div><div>Questions on my mind: What is the status of Ranges? Is there a=
current proposal that people are agreeing on? Is it being improved and doe=
s it have open consideration for standardization in its current form? =
Is it based on Boost?</div><div><br></div><div>I've found a (quiet) mailing=
list: <a href=3D"http://www.open-std.org/pipermail/ranges/">http://ww=
w.open-std.org/pipermail/ranges/</a></div><div><br></div><div>I also ran ac=
ross a document by Jeffrey Yasskin from jan.2012: <a href=3D"http://ww=
w.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html">http://www.open-=
std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html</a></div><div><br></div>=
<div>As well as some mentions in the lists.</div><div><br></div><div>If ran=
ges are coming along well, there is likely one source I can go to which wou=
ld answer all these questions. Unfortunately, I cannot find that. Sorry - I=
am new here =3D\<br></div><div><br></div><div>Prior to reviewing the range=
proposal: A range implementation could be made to be significantly more co=
mplex than a representation of contiguous elements (sequence). If the =
range proposal exists and happens to be complex, then it might generally be=
regarded as a distinct type which is aimed at solving a different problem.=
</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_107_1700322.1371149898026--
.
Author: carrierandoperator@yahoo.co.uk
Date: Thu, 13 Jun 2013 13:37:03 -0700 (PDT)
Raw View
------=_Part_242_17808406.1371155823478
Content-Type: text/plain; charset=ISO-8859-1
On Thursday, June 13, 2013 1:09:01 PM UTC-4, Olaf van der Spek wrote:
>
> What's the diff with r1?
Highlighting some of the new details:
1. Variants sequence_n<>, mutable_sequence_n<>, octet_sequence, and
mutable_octet_sequence were added
2. In the first rev, I suggested people may prefer derivation, but chose
to stick with the original implementation upon review (where mutable is a
separate type).
3. Comparison to proposed array_ref, as requested.
4. Noted that the sequence may not be empty, based on the original. If
that holds, then empty() could be removed. I suspect there will be some
resistance to that.
5. I also added some constructors and enhanced type checking when
creating the basic implementation.
But there are other details, explanations, and rationale in this rev --
it's several times larger than the first.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_242_17808406.1371155823478
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Thursday, June 13, 2013 1:09:01 PM UTC-4, Olaf van der Spek wrote:<block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;">What's the diff with r1?</blockquote=
><div><br></div><div> Highlighting some of the new details:</div><div>=
<ol><li>Variants sequence_n<>, mutable_sequence_n<>, octet=
_sequence, and mutable_octet_sequence were added<br></li><li>In the first r=
ev, I suggested people may prefer derivation, but chose to stick with the o=
riginal implementation upon review (where mutable is a separate type).<br><=
/li><li>Comparison to proposed array_ref, as requested.<br></li><li>Noted t=
hat the sequence may not be empty, based on the original. If that holds, th=
en empty() could be removed. I suspect there will be some resistance to tha=
t.<br></li><li>I also added some constructors and enhanced type checking wh=
en creating the basic implementation.<br></li></ol></div><div>But there are=
other details, explanations, and rationale in this rev -- it's several tim=
es larger than the first.</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_242_17808406.1371155823478--
.
Author: Alex B <devalexb@gmail.com>
Date: Fri, 14 Jun 2013 07:11:07 -0700 (PDT)
Raw View
------=_Part_855_27617074.1371219067514
Content-Type: text/plain; charset=ISO-8859-1
Here are several comments about your proposal.
1. The name is very confusing. In the standard, a *sequence container* is
simply a container that can be accessed sequentially. That means std::list
and std::deque are sequence containers; yet those types cannot be
represented by your *sequence* class. The only containers that your class
can refer to are *containers with contiguous storage* (that is arrays,
vectors and dynarrays). So the name is misleading. Maybe you should stick
with the array_ref name or find a better one.
2. Your data members are const. Why is that so? From what I understand it
is the reason why you don't make the class assignable or modifiable.
Reading from you previous thread, the reason you give is performance gain.
However I did not find anything to convince me that there could actually be
a performance gain, and you're not talking about it in this thread. Can you
please provide a concrete use-case where you expect that gain?
3. Why impose that size > 0 ? You even have a empty() function. Will that
mean that if I pass a vector to a function taking a sequence will result in
undefined behavior if the vector is empty? That means that users will have
to produce a lot of unnecessary tests to determine if the container is
empty before converting to a sequence. For me, a sequence/array_ref should
behave just like a container with contiguous storage that could not be
resized. And these *can* be empty (without a problem). So why have this
requirement for your class?
And other tidbits:
4. Why is this constructor explicit: template <class Tp, size_t N> explicit
sequence(Tp (&array)[N]);
5. About the constructor taking a pair of iterators (that is this one: template
<class Tp> sequence(Tp a, Tp b))
: how will you detect that the iterators are iterators of a container with
contiguous data storage? I don't think there is anything currently in the
standard to detect this. Testing for random_access_iterator_tag is not
enough; a deque has random access yet its content is not allocated
contiguously.
6. Shouldn't the function sequence::data() return a const_pointer instead?
And shouldn't mutable_sequence::data() return pointer (not const) instead?
7. How can this constructor work: template <class Tp> sequence(const
sequence<Tp>& p);
When would it make sense to construct a sequence from a sequence of another
type?
8. Can you provide a link to your full implementation? That would help
understand some of you undocumented intents.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_855_27617074.1371219067514
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Here are several comments about your proposal.<div><br></div><div>1. The na=
me is very confusing. In the standard, a <b>sequence container</b> is simpl=
y a container that can be accessed sequentially. That means std::list and s=
td::deque are sequence containers; yet those types cannot be represented by=
your <b>sequence</b> class. The only containers that your class can r=
efer to are <b>containers with contiguous storage</b> (that is arrays, vect=
ors and dynarrays). So the name is misleading. Maybe you should stick with =
the array_ref name or find a better one.</div><div><br></div><div>2. Your d=
ata members are const. Why is that so? From what I understand it is the rea=
son why you don't make the class assignable or modifiable. Reading from you=
previous thread, the reason you give is performance gain. However I did no=
t find anything to convince me that there could actually be a performance g=
ain, and you're not talking about it in this thread. Can you please provide=
a concrete use-case where you expect that gain?</div><div><br></div><div>3=
.. Why impose that size > 0 ? You even have a empty() function. Will that=
mean that if I pass a vector to a function taking a sequence will result i=
n undefined behavior if the vector is empty? That means that users will hav=
e to produce a lot of unnecessary tests to determine if the container is em=
pty before converting to a sequence. For me, a sequence/array_ref should be=
have just like a container with contiguous storage that could not be resize=
d. And these <b>can</b> be empty (without a problem). So why have this=
requirement for your class?</div><div><br></div><div>And other tidbits:</d=
iv><div><br></div><div>4. Why is this constructor explicit: <span styl=
e=3D"font-family: monospace; background-color: rgb(250, 250, 250);">templat=
e <class Tp, size_t N> explicit sequence(Tp (&array)[N]);</span><=
br><br>5. About the constructor taking a pair of iterators (that is this on=
e: <span style=3D"font-family: monospace; background-color: rgb(250, 2=
50, 250);">template <class Tp> sequence(Tp a, Tp b))</span><br>: how =
will you detect that the iterators are iterators of a container with contig=
uous data storage? I don't think there is anything currently in the standar=
d to detect this. Testing for random_access_iterator_tag is not enough; a d=
eque has random access yet its content is not allocated contiguously.</div>=
<div><br></div><div>6. Shouldn't the function sequence::data() return a con=
st_pointer instead? And shouldn't mutable_sequence::data() return pointer (=
not const) instead?</div><div><br></div><div>7. How can this constructor wo=
rk: <span style=3D"background-color: rgb(250, 250, 250); font-family: =
monospace;"> template <class Tp> sequence(const sequence<Tp&g=
t;& p);</span> </div><div>When would it make sense to construct a =
sequence from a sequence of another type?</div><div><br></div><div>8. Can y=
ou provide a link to your full implementation? That would help understand s=
ome of you undocumented intents.</div><div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_855_27617074.1371219067514--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Fri, 14 Jun 2013 12:12:23 -0500
Raw View
--001a11c1f4a20e3ced04df205c2d
Content-Type: text/plain; charset=ISO-8859-1
On 14 June 2013 09:11, Alex B <devalexb@gmail.com> wrote:
> Here are several comments about your proposal.
+1 on all your points.
3. Why impose that size > 0 ? You even have a empty() function. Will that
> mean that if I pass a vector to a function taking a sequence will result in
> undefined behavior if the vector is empty? That means that users will have
> to produce a lot of unnecessary tests to determine if the container is
> empty before converting to a sequence. For me, a sequence/array_ref should
> behave just like a container with contiguous storage that could not be
> resized. And these *can* be empty (without a problem). So why have this
> requirement for your class?
>
This one is a show stopper for me. Empty ranges are perfectly valid, and
unlike the author of this proposal, I find that allowing them simplifies a
lot of my code.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c1f4a20e3ced04df205c2d
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 14 June 2013 09:11, Alex B <span dir=3D"ltr"><<a href=3D"mailto:deval=
exb@gmail.com" target=3D"_blank">devalexb@gmail.com</a>></span> wrote:<b=
r><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Here are several comments about your proposal.</blockquote><div><br>+1 on a=
ll your points.<br><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>3. Why imp=
ose that size > 0 ? You even have a empty() function. Will that mean tha=
t if I pass a vector to a function taking a sequence will result in undefin=
ed behavior if the vector is empty? That means that users will have to prod=
uce a lot of unnecessary tests to determine if the container is empty befor=
e converting to a sequence. For me, a sequence/array_ref should behave just=
like a container with contiguous storage that could not be resized. And th=
ese <b>can</b>=A0be empty (without a problem). So why have this requirement=
for your class?</div>
</blockquote><div><br>This one is a show stopper for me.=A0 Empty ranges ar=
e perfectly valid, and unlike the author of this proposal, I find that allo=
wing them simplifies a lot of my code.<br></div></div>-- <br>=A0Nevin "=
;:-)" Liber=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com" ta=
rget=3D"_blank">nevin@eviloverlord.com</a>>=A0 (847) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--001a11c1f4a20e3ced04df205c2d--
.
Author: cartec69@gmail.com
Date: Fri, 14 Jun 2013 10:34:30 -0700 (PDT)
Raw View
------=_Part_974_25658875.1371231270086
Content-Type: text/plain; charset=ISO-8859-1
On Friday, June 14, 2013 12:12:23 PM UTC-5, Nevin ":-)" Liber wrote:
>
>
> This one is a show stopper for me. Empty ranges are perfectly valid, and
> unlike the author of this proposal, I find that allowing them simplifies a
> lot of my code.
>
What is the default constructed state for {mutable_}sequence if not an
empty range? I see default constructors for both classes in the proposal,
what do they do?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_974_25658875.1371231270086
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br>On Friday, June 14, 2013 12:12:23 PM UTC-5, Nevin ":-)" Liber wrote:<bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div class=3D"gmail_quote"><div><=
br>This one is a show stopper for me. Empty ranges are perfectly vali=
d, and unlike the author of this proposal, I find that allowing them simpli=
fies a lot of my code.</div></div></blockquote><div><br></div><div>What is =
the default constructed state for {mutable_}sequence if not an empty range?=
I see default constructors for both classes in the proposal, what do they =
do?</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_974_25658875.1371231270086--
.
Author: carrierandoperator@yahoo.co.uk
Date: Fri, 14 Jun 2013 11:15:14 -0700 (PDT)
Raw View
------=_Part_474_10978361.1371233714717
Content-Type: text/plain; charset=ISO-8859-1
On Friday, June 14, 2013 1:34:30 PM UTC-4, cart...@gmail.com wrote:
>
>
> On Friday, June 14, 2013 12:12:23 PM UTC-5, Nevin ":-)" Liber wrote:
>>
>>
>> This one is a show stopper for me. Empty ranges are perfectly valid, and
>> unlike the author of this proposal, I find that allowing them simplifies a
>> lot of my code.
>>
>
> What is the default constructed state for {mutable_}sequence if not an
> empty range? I see default constructors for both classes in the proposal,
> what do they do?
>
Oops - Leaving the default constructor in was an oversight on my part, and
should have been omitted because it conflicts with the wording in the
proposal.
The example interface (above) was reduced from a draft implementation. In
the first round, I said: "I think the next logical step would be for me to
float a basic implementation you all can try out where features such as
assignment can be enabled via the preprocessor.". So the ability to resize,
shrink, and assign in an initial implementation (which btw has not yet been
distributed) is something I intended to enable conditionally using the
preprocessor. That's the reason it existed in the first place. If the
members were not const, then it seems that the type should also represent 0
elements and in that scenario the default constructor and empty() are
sensible.
(just a quick correction before posting a full response to Alex)
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_474_10978361.1371233714717
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Friday, June 14, 2013 1:34:30 PM UTC-4, cart...@gmail.com wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><br>On Friday, June 14, 2013 1=
2:12:23 PM UTC-5, Nevin ":-)" Liber wrote:<blockquote class=3D"gmail_quote"=
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-lef=
t:1ex"><div class=3D"gmail_quote"><div><br>This one is a show stopper for m=
e. Empty ranges are perfectly valid, and unlike the author of this pr=
oposal, I find that allowing them simplifies a lot of my code.</div></div><=
/blockquote><div><br></div><div>What is the default constructed state for {=
mutable_}sequence if not an empty range? I see default constructors for bot=
h classes in the proposal, what do they do?</div></blockquote><div><br></di=
v><div>Oops - Leaving the default constructor in was an oversight on my par=
t, and should have been omitted because it conflicts with the wording in th=
e proposal.</div><div><br></div><div>The example interface (above) was redu=
ced from a draft implementation. In the first round, I said: "I think the n=
ext logical step would be for me to float a basic implementation you all ca=
n try out where features such as assignment can be enabled via the preproce=
ssor.". So the ability to resize, shrink, and assign in an initial implemen=
tation (which btw has not yet been distributed) is something I intended to =
enable conditionally using the preprocessor. That's the reason it existed i=
n the first place. If the members were not const, then it seems that the ty=
pe should also represent 0 elements and in that scenario the default constr=
uctor and empty() are sensible.</div><div><br></div><div>(just a quick corr=
ection before posting a full response to Alex)</div><div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_474_10978361.1371233714717--
.
Author: carrierandoperator@yahoo.co.uk
Date: Fri, 14 Jun 2013 16:22:28 -0700 (PDT)
Raw View
------=_Part_1171_26082656.1371252148298
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
On Friday, June 14, 2013 10:11:07 AM UTC-4, Alex B wrote:
>
> Here are several comments about your proposal.
>
> 1. The name is very confusing. In the standard, a *sequence container* is=
=20
> simply a container that can be accessed sequentially. That means std::lis=
t=20
> and std::deque are sequence containers; yet those types cannot be=20
> represented by your *sequence* class. The only containers that your class=
=20
> can refer to are *containers with contiguous storage* (that is arrays,=20
> vectors and dynarrays). So the name is misleading. Maybe you should stick=
=20
> with the array_ref name or find a better one.
>
>
It's just a contiguous sequence of T. Like the standard mentions "character=
=20
sequence" or "byte sequence" or "The header <array> defines a class=20
template for storing fixed-size sequences of objects.". It's not meant to=
=20
conflict with sequence *containers*. One could say contiguous_sequence<>=20
and mutable_contiguous_sequence<>, but I find that "wordy" compared to=20
other types in the standard library. I've added a document where=20
suggestions for alternate names may be recorded.
=20
> 2. Your data members are const. Why is that so? From what I understand it=
=20
> is the reason why you don't make the class assignable or modifiable.=20
> Reading from you previous thread, the reason you give is performance gain=
..=20
> However I did not find anything to convince me that there could actually =
be=20
> a performance gain, and you're not talking about it in this thread. Can y=
ou=20
> please provide a concrete use-case where you expect that gain?
>
Sorry, performance is *not* the primary reason. Sequences are to designed=
=20
to introduce reference-like semantics to arrays, and I hope to keep them=20
close to the essence of achieving that.
=20
>
> 3. Why impose that size > 0 ?
>
In my implementation, empty sequences are forbidden. That is by design.=20
I've lived with this constraint in my implementation for years and have no=
=20
desire or need to permit empty sequences in that implementation. I don't=20
consider it a nuisance, but an aid. It increases memory safety, and=20
provides narrow semantics similar to references.
Because I found reference-like semantics were adequate (a _feature_, in=20
fact), I decided to also apply them to this proposed type. And yes, I=20
figured there would be resistance to that idea. And yes, I am willing to=20
lift that restriction if a majority says they favor empty sequences=20
(ideally, that would be demonstrated by examples of why they really are=20
necessary). After all, the implementation is for everybody rather than for=
=20
my needs. Another possibile approach would be to make that condition a=20
template parameter. I don't find that necessary=85 but if it is the major=
=20
halting point, then I will consider such changes.
So I've proven to myself that reference-like semantics are possible and=20
regard them to be very beneficial, but they aren't something you could=20
introduce after the fact without breaking changes so now is the appropriate=
=20
time to push for them.
The route I am taking is (if this gains traction) to provide an=20
implementation where either:
1. reference-like semantics are enforced or
2. members will not be const (and empty is permitted).
=20
Then people can play with it and see for themselves how much of a nuisance=
=20
an approach really is. But I do realize that it does remove capabilities=20
people are accustomed to having and that it's a pretty big *change* from=20
what many are used to. I've found that change is a good one, but I know=20
some will disagree or say they see no great benefit in narrowing the=20
capabilities of a pointer+size. The ability to use pointer and size isn't=
=20
going to be removed. Iterators and range implementations won't disappear.=
=20
It's just another tool in the toolbox. It does not attempt to solve=20
everything which can be accomplished with a pointer and size. Rather,=20
sequences attempt to solve a very narrow problem, without introducing=20
complexities (or functionality) found in types like iterator or range=20
implementations. Creating an object which focuses on the essence of a=20
problem is a fine ideal.
Note: When I write "my implementation", I mean the implementation that I=20
wrote and exists in my codebase -- not identical to the result of this=20
proposal (if that materializes).
=20
> You even have a empty() function.
>
empty() and default ctor were left in by mistake. I had acknowledged that=
=20
empty() was strictly unnecessary if the type keeps semantics similar to a=
=20
reference. In the discussion of first rev, I said I'd provide an=20
implementation where non-const member mode could be enabled by the=20
preprocessor and some bits specific to that implementation were not omitted=
=20
when reducing the interface from the prototype. Further explanation in=20
response to cart=85@gmail.com.
=20
> Will that mean that if I pass a vector to a function taking a sequence=20
> will result in undefined behavior if the vector is empty?
>
Either that or throw an exception. Whichever response would be least=20
surprising.
Personally, I favor saying that passing an empty vector (or other invalid=
=20
parameters) is UB (again, keeping with references). Of course, library=20
implementors can add error detection to their debug mode. The reason I=20
favor UB is that relying on exceptions here can make this type heavy (in=20
relation to what is attempting to replace), and I'd really favor a minimal=
=20
overhead abstraction in the end.
=20
> That means that users will have to produce a lot of unnecessary tests to=
=20
> determine if the container is empty before converting to a sequence.
>
I disagree. It localizes that logic and error to precisely where it needs=
=20
to be, forbidding the error from propagating (or continuing in a defined=20
manner). I don't disagree that it requires logic at construction, just that=
=20
that logic and validation is moved out of the implementations (e.g. which=
=20
take sequences as parameters) to the callee (where they belong).
When you read/write defensive C (e.g. which validates parameters), do you=
=20
sometimes really miss having references where pointers are used? With a=20
reference, you don't need to check the pointer which was passed. Similarly,=
=20
if the sequence does not represent zero elements then there is one more=20
guarantee you can rely on when passing arrays around. So it means that when=
=20
constructing a sequence, one intends to bind an array (or sub-array of a=20
physical array) of objects to that sequence. Once it is a sequence, it=20
lifts a ton of error detection (as well as documentation) out of any=20
implementation which takes a sequence as a parameter. When one sees `void=
=20
foo(std::sequence<int>)`, they would know that they must by contract=20
represent at least one element, and the definition need not check that the=
=20
array is empty/Null. Where the array is optional -- wouldn't you agree that=
=20
it makes more sense to have a separate function? Either that, or at least=
=20
make it syntactically obvious that it is optional? I believe so. Where an=
=20
optional parameter is favored, then everybody still has the facilities to=
=20
use what they use today (in addition to the option to pass by=20
pointer-to-sequence<>).
Here's a paper which supports using narrower contracts:=20
http://isocpp.org/files/papers/n3604.pdf
=20
> For me, a sequence/array_ref should behave just like a container with=20
> contiguous storage that could not be resized. And these *can* be empty=20
> (without a problem). So why have this requirement for your class?
>
And that's a very fair point.
=20
> 4. Why is this constructor explicit: template <class Tp, size_t N>=20
> explicit sequence(Tp (&array)[N]);
>
The initial/draft implementation (which was used for the code above) is not=
=20
written to great standards or been reviewed. I read that the committee=20
favors single parameter constructors to have explicit qualification where=
=20
possible. Should it not be so?
=20
> 5. About the constructor taking a pair of iterators (that is this one: te=
mplate=20
> <class Tp> sequence(Tp a, Tp b))
> : how will you detect that the iterators are iterators of a container wit=
h=20
> contiguous data storage? I don't think there is anything currently in the=
=20
> standard to detect this. Testing for random_access_iterator_tag is not=20
> enough; a deque has random access yet its content is not allocated=20
> contiguously.
>
That constructor is meant for pointers, but forward iterators could be=20
considered. I've written up the draft implementation where forward=20
iterators of contiguous elements are simply pointers. I've not built/tested=
=20
this implementation on many systems yet.
I mentioned that some additional checking exists, which is not present in=
=20
the interface. The implementation picked up on those issues you pointed out=
=20
when building using clang/libc++. So the implementation tests whether the=
=20
parameters are pointers and convertible to the type specified in the=20
parameter list and the program failed to compile because they actually=20
return concrete iterator types (not pointers). Of course, that is an=20
implementation detail and if that guarantee cannot be met, then the=20
constructor could be removed and sequence(T*,size_type) would still exist=
=20
for those "trust me" incidents.
=20
> 6. Shouldn't the function sequence::data() return a const_pointer instead=
?
>
You mean to use the typedef rather than const value_type* (after all, it is=
=20
the same)? The wording in the C++11 final working draft uses `const T*`=20
rather than the const_pointer typedef when detailing std::vector<> and=20
std::array<>. Therefore, I stuck with that.
=20
> And shouldn't mutable_sequence::data() return pointer (not const) instead=
?
>
I disagree. I consider these declarations correct as proposed. This is a=20
case where the type steps away from the behavior of a raw pointer and=20
introduces const in the right place and for the right reason. const should=
=20
be transitive to the elements it represents for this type. std::vector<>=20
and std::array<> both return const pointers from their const-qualified=20
data() member functions (23.3.6.4).
7. How can this constructor work: template <class Tp> sequence(const=20
> sequence<Tp>& p);=20
> When would it make sense to construct a sequence from a sequence of=20
> another type?
>
Presently, this is supported (e.g. via a conversion similar to what we see=
=20
using enable_if statements) when:
1. the type is the same
2. or the size and alignment are the same and value_type is a common=20
base.
=20
Using:
struct A {char a;};
struct B : A {char b;};
struct C : A {};
This can permit the construction of sequence<A> from an array of C,=20
although B is likely to fail. I consider this conversion check naive in its=
=20
current form. It may also be undesirable because it can expose=20
implementation/ABI specific conversions (although that can also be=20
desirable).
=20
> 8. Can you provide a link to your full implementation? That would help=20
> understand some of you undocumented intents.
>
I will when it's ready. Whether I finish it and the supporting tests and=20
cross platform testing also depends on people's reaction/support for the=20
proposal.
Speaking of which, if you or anybody else would be willing to review that=
=20
draft implementation before it goes public, let me know. I'd appreciate it.
Thanks for all your feedback, Alex.
=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1171_26082656.1371252148298
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
<br><br>On Friday, June 14, 2013 10:11:07 AM UTC-4, Alex B wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;">Here are several comments about your pro=
posal.<div><br></div><div>1. The name is very confusing. In the standard, a=
<b>sequence container</b> is simply a container that can be accessed seque=
ntially. That means std::list and std::deque are sequence containers; yet t=
hose types cannot be represented by your <b>sequence</b> class. The on=
ly containers that your class can refer to are <b>containers with contiguou=
s storage</b> (that is arrays, vectors and dynarrays). So the name is misle=
ading. Maybe you should stick with the array_ref name or find a better one.=
</div><div><br></div></blockquote><div><br></div><div>It's just a contiguou=
s sequence of T. Like the standard mentions "character sequence" or "byte s=
equence" or "The header <array> defines a class template for storing =
fixed-size sequences of objects.". It's not meant to conflict with sequence=
*containers*. One could say contiguous_sequence<> and mutable_contig=
uous_sequence<>, but I find that "wordy" compared to other types in t=
he standard library. I've added a document where suggestions for alternate =
names may be recorded.</div><div> </div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div></div><div>2. Your data members are const. Why is that =
so? From what I understand it is the reason why you don't make the class as=
signable or modifiable. Reading from you previous thread, the reason you gi=
ve is performance gain. However I did not find anything to convince me that=
there could actually be a performance gain, and you're not talking about i=
t in this thread. Can you please provide a concrete use-case where you expe=
ct that gain?</div></blockquote><div><br></div><div>Sorry, performance is *=
not* the primary reason. Sequences are to designed to introduce reference-l=
ike semantics to arrays, and I hope to keep them close to the essence of ac=
hieving that.</div><div> </div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div><br></div><div>3. Why impose that size > 0 ?</div></blockquot=
e><div><br></div><div>In my implementation, empty sequences are forbidden. =
That is by design. I've lived with this constraint in my implementation for=
years and have no desire or need to permit empty sequences in that impleme=
ntation. I don't consider it a nuisance, but an aid. It increases memory sa=
fety, and provides narrow semantics similar to references.</div><div><br></=
div><div>Because I found reference-like semantics were adequate (a _feature=
_, in fact), I decided to also apply them to this proposed type. And yes, I=
figured there would be resistance to that idea. And yes, I am willing to l=
ift that restriction if a majority says they favor empty sequences (ideally=
, that would be demonstrated by examples of why they really are necessary).=
After all, the implementation is for everybody rather than for my needs. A=
nother possibile approach would be to make that condition a template parame=
ter. I don't find that necessary=85 but if it is the major halting point, t=
hen I will consider such changes.</div><div><br></div><div>So I've proven t=
o myself that reference-like semantics are possible and regard them to be v=
ery beneficial, but they aren't something you could introduce after the fac=
t without breaking changes so now is the appropriate time to push for them.=
</div><div><br></div><div>The route I am taking is (if this gains traction)=
to provide an implementation where either:</div><div><ol><li>reference-lik=
e semantics are enforced or<br></li><li>members will not be const (and empt=
y is permitted).<br></li></ol></div><div><br></div><div>Then people can pla=
y with it and see for themselves how much of a nuisance an approach really =
is. But I do realize that it does remove capabilities people are accustomed=
to having and that it's a pretty big <b>change</b> from what many are used=
to. I've found that change is a good one, but I know some will disagree or=
say they see no great benefit in narrowing the capabilities of a pointer+s=
ize. The ability to use pointer and size isn't going to be removed. Iterato=
rs and range implementations won't disappear. It's just another tool in the=
toolbox. It does not attempt to solve everything which can be accomplished=
with a pointer and size. Rather, sequences attempt to solve a very narrow =
problem, without introducing complexities (or functionality) found in types=
like iterator or range implementations. Creating an object which focuses o=
n the essence of a problem is a fine ideal.</div><div><br></div><div>Note: =
When I write "my implementation", I mean the implementation that I wrote an=
d exists in my codebase -- not identical to the result of this proposal (if=
that materializes).</div><div> </div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;"><div>You even have a empty() function.</div></blockquote><div>=
<br></div><div>empty() and default ctor were left in by mistake. I had ackn=
owledged that empty() was strictly unnecessary if the type keeps semantics =
similar to a reference. In the discussion of first rev, I said I'd provide =
an implementation where non-const member mode could be enabled by the prepr=
ocessor and some bits specific to that implementation were not omitted when=
reducing the interface from the prototype. Further explanation in response=
to cart=85@gmail.com.</div><div><br></div><div> </div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div>Will that mean that if I pass a vector t=
o a function taking a sequence will result in undefined behavior if the vec=
tor is empty?</div></blockquote><div><br></div><div>Either that or throw an=
exception. Whichever response would be least surprising.</div><div><br></d=
iv><div>Personally, I favor saying that passing an empty vector (or other i=
nvalid parameters) is UB (again, keeping with references). Of course, libra=
ry implementors can add error detection to their debug mode. The reason I f=
avor UB is that relying on exceptions here can make this type heavy (in rel=
ation to what is attempting to replace), and I'd really favor a minimal ove=
rhead abstraction in the end.</div><div> </div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div>That means that users will have to produce a lot=
of unnecessary tests to determine if the container is empty before convert=
ing to a sequence.</div></blockquote><div><br></div><div>I disagree. It loc=
alizes that logic and error to precisely where it needs to be, forbidding t=
he error from propagating (or continuing in a defined manner). I don't disa=
gree that it requires logic at construction, just that that logic and valid=
ation is moved out of the implementations (e.g. which take sequences as par=
ameters) to the callee (where they belong).</div><div><br></div><div>When y=
ou read/write defensive C (e.g. which validates parameters), do you sometim=
es really miss having references where pointers are used? With a reference,=
you don't need to check the pointer which was passed. Similarly, if the se=
quence does not represent zero elements then there is one more guarantee yo=
u can rely on when passing arrays around. So it means that when constructin=
g a sequence, one intends to bind an array (or sub-array of a physical arra=
y) of objects to that sequence. Once it is a sequence, it lifts a ton of er=
ror detection (as well as documentation) out of any implementation which ta=
kes a sequence as a parameter. When one sees `void foo(std::sequence<int=
>)`, they would know that they must by contract represent at least one e=
lement, and the definition need not check that the array is empty/Null. Whe=
re the array is optional -- wouldn't you agree that it makes more sense to =
have a separate function? Either that, or at least make it syntactically ob=
vious that it is optional? I believe so. Where an optional parameter is fav=
ored, then everybody still has the facilities to use what they use today (i=
n addition to the option to pass by pointer-to-sequence<>).</div><div=
><br></div><div>Here's a paper which supports using narrower contracts:&nbs=
p;<a href=3D"http://isocpp.org/files/papers/n3604.pdf">http://isocpp.org/fi=
les/papers/n3604.pdf</a></div><div><br></div><div> </div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;"><div>For me, a sequence/array_ref should be=
have just like a container with contiguous storage that could not be resize=
d. And these <b>can</b> be empty (without a problem). So why have this=
requirement for your class?</div></blockquote><div><br></div><div><div>And=
that's a very fair point.</div></div><div><br></div><div> <br></div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div>4. Why is this constructor=
explicit: <span style=3D"font-family: monospace; background-color: rg=
b(250, 250, 250); ">template <class Tp, size_t N> explicit sequence(T=
p (&array)[N]);</span></div></blockquote><div><br></div><div><div>The i=
nitial/draft implementation (which was used for the code above) is not writ=
ten to great standards or been reviewed. I read that the committee favors s=
ingle parameter constructors to have explicit qualification where possible.=
Should it not be so?</div></div><div><br></div><div> </div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div>5. About the constructor taking a p=
air of iterators (that is this one: <span style=3D"font-family: monosp=
ace; background-color: rgb(250, 250, 250); ">template <class Tp> sequ=
ence(Tp a, Tp b))</span><br></div><div>: how will you detect that the itera=
tors are iterators of a container with contiguous data storage? I don't thi=
nk there is anything currently in the standard to detect this. Testing for =
random_access_iterator_tag is not enough; a deque has random access yet its=
content is not allocated contiguously.</div></blockquote><div><br></div><d=
iv>That constructor is meant for pointers, but forward iterators could be c=
onsidered. I've written up the draft implementation where forward iterators=
of contiguous elements are simply pointers. I've not built/tested this imp=
lementation on many systems yet.</div><div><br></div><div>I mentioned that =
some additional checking exists, which is not present in the interface. The=
implementation picked up on those issues you pointed out when building usi=
ng clang/libc++. So the implementation tests whether the parameters are poi=
nters and convertible to the type specified in the parameter list and the p=
rogram failed to compile because they actually return concrete iterator typ=
es (not pointers). Of course, that is an implementation detail and if that =
guarantee cannot be met, then the constructor could be removed and sequence=
(T*,size_type) would still exist for those "trust me" incidents.</div><div>=
<br></div><div> </div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v>6. Shouldn't the function sequence::data() return a const_pointer instead=
?</div></blockquote><div><br></div><div>You mean to use the typedef rather =
than const value_type* (after all, it is the same)? The wording in the C++1=
1 final working draft uses `const T*` rather than the const_pointer typedef=
when detailing std::vector<> and std::array<>. Therefore, I st=
uck with that.</div><div> </div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div>And shouldn't mutable_sequence::data() return pointer (not cons=
t) instead?<br></div></blockquote><div><br></div><div><div>I disagree. I co=
nsider these declarations correct as proposed. This is a case where the typ=
e steps away from the behavior of a raw pointer and introduces const in the=
right place and for the right reason. const should be transitive to the el=
ements it represents for this type. std::vector<> and std::array<&=
gt; both return const pointers from their const-qualified data() member fun=
ctions (23.3.6.4).</div></div><div><br></div><div><br></div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div></div><div>7. How can this constructor w=
ork: <span style=3D"background-color: rgb(250, 250, 250); font-family:=
monospace; "> template <class Tp> sequence(const sequence<Tp=
>& p);</span> <br></div><div>When would it make sense to constr=
uct a sequence from a sequence of another type?</div></blockquote><div><br>=
</div><div><div>Presently, this is supported (e.g. via a conversion similar=
to what we see using enable_if statements) when:</div><div><ol><li>the typ=
e is the same<br></li><li>or the size and alignment are the same and value_=
type is a common base.<br></li></ol></div><div><br></div><div>Using:</div><=
div><br></div><div style=3D"background-color: rgb(250, 250, 250); border: 1=
px solid rgb(187, 187, 187); word-wrap: break-word; " class=3D"prettyprint"=
><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> A </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">{</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">char</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> a</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">;};</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">str=
uct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> B </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">:</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> A </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">char</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> b</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;};</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">struct</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> C </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> A =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{};</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div>=
</code></div><div><br><br></div><div>This can permit the construction of se=
quence<A> from an array of C, although B is likely to fail. I conside=
r this conversion check naive in its current form. It may also be undesirab=
le because it can expose implementation/ABI specific conversions (although =
that can also be desirable).</div></div><div><br></div><div> </div><bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div>8. Can you provide a link to=
your full implementation? That would help understand some of you undocumen=
ted intents.</div></blockquote><div><br></div><div><br></div><div>I will wh=
en it's ready. Whether I finish it and the supporting tests and cross platf=
orm testing also depends on people's reaction/support for the proposal.</di=
v><div><br></div><div>Speaking of which, if you or anybody else would be wi=
lling to review that draft implementation before it goes public, let me kno=
w. I'd appreciate it.</div><div><br></div><div>Thanks for all your feedback=
, Alex.</div><div><br></div><div> </div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_1171_26082656.1371252148298--
.
Author: carrierandoperator@yahoo.co.uk
Date: Fri, 14 Jun 2013 16:33:14 -0700 (PDT)
Raw View
------=_Part_1465_20905687.1371252794567
Content-Type: text/plain; charset=ISO-8859-1
On Friday, June 14, 2013 1:12:23 PM UTC-4, Nevin ":-)" Liber wrote:
>
> On 14 June 2013 09:11, Alex B <deva...@gmail.com <javascript:>> wrote:
>
>> Here are several comments about your proposal.
>
>
> +1 on all your points.
>
> 3. Why impose that size > 0 ? You even have a empty() function. Will that
>> mean that if I pass a vector to a function taking a sequence will result in
>> undefined behavior if the vector is empty? That means that users will have
>> to produce a lot of unnecessary tests to determine if the container is
>> empty before converting to a sequence. For me, a sequence/array_ref should
>> behave just like a container with contiguous storage that could not be
>> resized. And these *can* be empty (without a problem). So why have this
>> requirement for your class?
>>
>
> This one is a show stopper for me. Empty ranges are perfectly valid, and
> unlike the author of this proposal, I find that allowing them simplifies a
> lot of my code.
> --
> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com <javascript:>> (847)
> 691-1404
I expanded on the benefit of reference-like semantics of sequences in
response to Alex, btw. I also intend to provide an implementation where
people can try this out for themselves and compare.
Thanks
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1465_20905687.1371252794567
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Friday, June 14, 2013 1:12:23 PM UTC-4, Nevin ":-)" Liber wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left=
: 1px #ccc solid;padding-left: 1ex;">On 14 June 2013 09:11, Alex B <span di=
r=3D"ltr"><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mail=
to=3D"__XYzorSy5IJ">deva...@gmail.com</a>></span> wrote:<br><div class=
=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex">
Here are several comments about your proposal.</blockquote><div><br>+1 on a=
ll your points.<br><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>3. Why imp=
ose that size > 0 ? You even have a empty() function. Will that mean tha=
t if I pass a vector to a function taking a sequence will result in undefin=
ed behavior if the vector is empty? That means that users will have to prod=
uce a lot of unnecessary tests to determine if the container is empty befor=
e converting to a sequence. For me, a sequence/array_ref should behave just=
like a container with contiguous storage that could not be resized. And th=
ese <b>can</b> be empty (without a problem). So why have this requirem=
ent for your class?</div>
</blockquote><div><br>This one is a show stopper for me. Empty ranges=
are perfectly valid, and unlike the author of this proposal, I find that a=
llowing them simplifies a lot of my code.<br></div></div>-- <br> Nevin=
":-)" Liber <mailto:<a href=3D"javascript:" target=3D"_blank" gdf=
-obfuscated-mailto=3D"__XYzorSy5IJ">ne...@eviloverlord.com</a><wbr>>&nbs=
p; (847) 691-1404</blockquote><div><br></div><div>I expanded on the benefit=
of reference-like semantics of sequences in response to Alex, btw. I also =
intend to provide an implementation where people can try this out for thems=
elves and compare.</div><div><br></div><div>Thanks</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_1465_20905687.1371252794567--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 15 Jun 2013 12:26:36 -0700 (PDT)
Raw View
------=_Part_1471_22875935.1371324396616
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
On Friday, June 14, 2013 4:22:28 PM UTC-7, carrieran...@yahoo.co.uk wrote:
>
> On Friday, June 14, 2013 10:11:07 AM UTC-4, Alex B wrote:
>>
>>
>> 3. Why impose that size > 0 ?
>>
>
> In my implementation, empty sequences are forbidden. That is by design.=
=20
> I've lived with this constraint in my implementation for years and have n=
o=20
> desire or need to permit empty sequences in that implementation. I don't=
=20
> consider it a nuisance, but an aid. It increases memory safety, and=20
> provides narrow semantics similar to references.
>
> Because I found reference-like semantics were adequate (a _feature_, in=
=20
> fact), I decided to also apply them to this proposed type. And yes, I=20
> figured there would be resistance to that idea. And yes, I am willing to=
=20
> lift that restriction if a majority says they favor empty sequences=20
> (ideally, that would be demonstrated by examples of why they really are=
=20
> necessary). After all, the implementation is for everybody rather than fo=
r=20
> my needs. Another possibile approach would be to make that condition a=20
> template parameter. I don't find that necessary=85 but if it is the major=
=20
> halting point, then I will consider such changes.
>
> So I've proven to myself that reference-like semantics are possible and=
=20
> regard them to be very beneficial, but they aren't something you could=20
> introduce after the fact without breaking changes so now is the appropria=
te=20
> time to push for them.
>
> The route I am taking is (if this gains traction) to provide an=20
> implementation where either:
>
> 1. reference-like semantics are enforced or
> 2. members will not be const (and empty is permitted).
> =20
>
> Then people can play with it and see for themselves how much of a nuisanc=
e=20
> an approach really is. But I do realize that it does remove capabilities=
=20
> people are accustomed to having and that it's a pretty big *change* from=
=20
> what many are used to. I've found that change is a good one, but I know=
=20
> some will disagree or say they see no great benefit in narrowing the=20
> capabilities of a pointer+size. The ability to use pointer and size isn't=
=20
> going to be removed. Iterators and range implementations won't disappear.=
=20
> It's just another tool in the toolbox. It does not attempt to solve=20
> everything which can be accomplished with a pointer and size. Rather,=20
> sequences attempt to solve a very narrow problem, without introducing=20
> complexities (or functionality) found in types like iterator or range=20
> implementations. Creating an object which focuses on the essence of a=20
> problem is a fine ideal.
>
> Note: When I write "my implementation", I mean the implementation that I=
=20
> wrote and exists in my codebase -- not identical to the result of this=20
> proposal (if that materializes).
>
I'm in total agreement with Nevin on this: this is a complete deal-breaker.
What is the most common operation performed on an arbitrary range of=20
contiguously-allocated elements? Iteration over that range. And every=20
function that iterates over a range of elements will operate just fine on=
=20
an *empty* range of elements. `for`, range-based `for`, `for_each`, *every=
=20
algorithm* in the entire standard library, all of the C-standard library=20
functions that take a pointer + a size, all of them will work just fine on=
=20
empty ranges. You have to actually *try* to write a loop over a range in=20
C++ that won't work for an empty range.
So your non-empty "sequence" reference would be the odd man out.
It also serves to make code needlessly obtuse. Take this function for=20
example:
void func(std::sequence sq)
{
if(sq.size() > 0)
return;
auto pair =3D sq.divide(1);
process_ranges(pair);
}
OK, what's in `pair`? The way you want it, it would contain a sequence of=
=20
one element and a sequence that *may or may not* be a legitimate value. You=
=20
can't even *ask* it if it is a legitimate sequence. Indeed, simply calling=
=20
`sq.divide(1)` on a range that doesn't have more than one element may=20
result in undefined behavior.
Why? I already checked that there was at least one value. Are you saying I=
=20
should have to do this:
void func(std::sequence sq)
{
if(sq.size() > 0)
return;
if(sq.size() > 1)
{
auto pair =3D sq.divide(1);
process_ranges(pair);
}
process_first_range(sq);
}
What good is that? I now have to split my `process_ranges` function into=20
two, one that takes two ranges and one that just takes one. The original=20
`process_ranges` function could have probably worked just fine with empty=
=20
ranges. But because of a completely arbitrary design limitation, my code=20
has to be split.
The only justification you've put forth for this is that you want the class=
=20
to have "reference semantics" and references can't be empty. But even that=
=20
is specious. A reference cannot be *invalid*. An empty sequence is still a =
*valid=20
sequence*, just like the empty set <http://en.wikipedia.org/wiki/Empty_set>=
is still a valid set. You may not be able to get anything from it, but=20
there are plenty of valid uses for an empty sequence. `begin/end` may not=
=20
return valid iterators, but they are required to return the *same* iterator=
=20
value, and thus you can iterate over them.
So why should we go against *decades* of user experience here?
And speaking of decades of experience, that applies to the whole "immutable=
=20
reference semantics" thing too. Pretty much every object in the C++=20
standard library since C++98 uses *value* semantics. Even the istreams work=
=20
by value-move; they just forbid copying. They're mutable by default; if you=
=20
want them to be immutable, you make them `const`. That's the *standard*.
The only objects that don't use pure value semantics are those that=20
explicitly reference things. And even those are by-*value* references:=20
std::reference_wrapper can be re-seated, as can std::shared_ptr, and any=20
other standard library reference-to-thing object.
So again, why should we go against how all other objects in the standard=20
work? You've proven to yourself that such an implementation *can* work and =
*
can* be useful. That's great. But that's not enough to say that it *should*=
be done, or that it should become=20
*standardized*.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1471_22875935.1371324396616
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
On Friday, June 14, 2013 4:22:28 PM UTC-7, carrieran...@yahoo.co.uk wrote:<=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;">On Friday, June 14, 2013 10:11:=
07 AM UTC-4, Alex B wrote:<blockquote class=3D"gmail_quote" style=3D"margin=
:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div><br>=
</div><div>3. Why impose that size > 0 ?</div></blockquote><div><br></di=
v><div>In my implementation, empty sequences are forbidden. That is by desi=
gn. I've lived with this constraint in my implementation for years and have=
no desire or need to permit empty sequences in that implementation. I don'=
t consider it a nuisance, but an aid. It increases memory safety, and provi=
des narrow semantics similar to references.</div><div><br></div><div>Becaus=
e I found reference-like semantics were adequate (a _feature_, in fact), I =
decided to also apply them to this proposed type. And yes, I figured there =
would be resistance to that idea. And yes, I am willing to lift that restri=
ction if a majority says they favor empty sequences (ideally, that would be=
demonstrated by examples of why they really are necessary). After all, the=
implementation is for everybody rather than for my needs. Another possibil=
e approach would be to make that condition a template parameter. I don't fi=
nd that necessary=85 but if it is the major halting point, then I will cons=
ider such changes.</div><div><br></div><div>So I've proven to myself that r=
eference-like semantics are possible and regard them to be very beneficial,=
but they aren't something you could introduce after the fact without break=
ing changes so now is the appropriate time to push for them.</div><div><br>=
</div><div>The route I am taking is (if this gains traction) to provide an =
implementation where either:</div><div><ol><li>reference-like semantics are=
enforced or<br></li><li>members will not be const (and empty is permitted)=
..<br></li></ol></div><div><br></div><div>Then people can play with it and s=
ee for themselves how much of a nuisance an approach really is. But I do re=
alize that it does remove capabilities people are accustomed to having and =
that it's a pretty big <b>change</b> from what many are used to. I've found=
that change is a good one, but I know some will disagree or say they see n=
o great benefit in narrowing the capabilities of a pointer+size. The abilit=
y to use pointer and size isn't going to be removed. Iterators and range im=
plementations won't disappear. It's just another tool in the toolbox. It do=
es not attempt to solve everything which can be accomplished with a pointer=
and size. Rather, sequences attempt to solve a very narrow problem, withou=
t introducing complexities (or functionality) found in types like iterator =
or range implementations. Creating an object which focuses on the essence o=
f a problem is a fine ideal.</div><div><br></div><div>Note: When I write "m=
y implementation", I mean the implementation that I wrote and exists in my =
codebase -- not identical to the result of this proposal (if that materiali=
zes).</div></blockquote><div><br>I'm in total agreement with Nevin on this:=
this is a complete deal-breaker.<br><br>What is the most common operation =
performed on an arbitrary range of contiguously-allocated elements? Iterati=
on over that range. And every function that iterates over a range of elemen=
ts will operate just fine on an <i>empty</i> range of elements. `for`, rang=
e-based `for`, `for_each`, <i>every algorithm</i> in the entire standard li=
brary, all of the C-standard library functions that take a pointer + a size=
, all of them will work just fine on empty ranges. You have to actually <i>=
try</i> to write a loop over a range in C++ that won't work for an empty ra=
nge.<br><br>So your non-empty "sequence" reference would be the odd man out=
..<br><br>It also serves to make code needlessly obtuse. Take this function =
for example:<br><br><div class=3D"prettyprint" style=3D"background-color: r=
gb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; b=
order-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div =
class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> func</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">sequence sq</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br> </span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">if</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">sq</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">size</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">></span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" =
class=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">return</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br><br> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> pair </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> sq</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">divide</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> process_ranges</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">pair</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">}</span></div></code></div><br>OK, what's in `pair`? The way you =
want it, it would contain a sequence of one element and a sequence that <i>=
may or may not</i> be a legitimate value. You can't even <i>ask</i> it if i=
t is a legitimate sequence. Indeed, simply calling `sq.divide(1)` on a rang=
e that doesn't have more than one element may result in undefined behavior.=
<br><br>Why? I already checked that there was at least one value. Are you s=
aying I should have to do this:<br><br><div class=3D"prettyprint" style=3D"=
background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bor=
der-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D=
"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">void</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> func</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">sequence=
sq</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">sq</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">size</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">></sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #066;" class=3D"styled-by-prettify">0</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br> </span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br><br> </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">if</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">sq</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
size</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br> </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br> </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> pair </span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> sq</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">divide</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span sty=
le=3D"color: #066;" class=3D"styled-by-prettify">1</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br> process_ranges</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">pair</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br><br> process_first_range</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">sq</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></div></code></div><br>What good is that? I now have to=
split my `process_ranges` function into two, one that takes two ranges and=
one that just takes one. The original `process_ranges` function could have=
probably worked just fine with empty ranges. But because of a completely a=
rbitrary design limitation, my code has to be split.<br><br>The only justif=
ication you've put forth for this is that you want the class to have "refer=
ence semantics" and references can't be empty. But even that is specious. A=
reference cannot be <i>invalid</i>. An empty sequence is still a <i>valid =
sequence</i>, just like the <a href=3D"http://en.wikipedia.org/wiki/Empty_s=
et">empty set</a> is still a valid set. You may not be able to get anything=
from it, but there are plenty of valid uses for an empty sequence. `begin/=
end` may not return valid iterators, but they are required to return the <i=
>same</i> iterator value, and thus you can iterate over them.<br><br>So why=
should we go against <i>decades</i> of user experience here?<br><br>And sp=
eaking of decades of experience, that applies to the whole "immutable refer=
ence semantics" thing too. Pretty much every object in the C++ standard lib=
rary since C++98 uses <i>value</i> semantics. Even the istreams work by val=
ue-move; they just forbid copying. They're mutable by default; if you want =
them to be immutable, you make them `const`. That's the <i>standard</i>.<br=
><br>The only objects that don't use pure value semantics are those that ex=
plicitly reference things. And even those are by-<i>value</i> references: s=
td::reference_wrapper can be re-seated, as can std::shared_ptr, and any oth=
er standard library reference-to-thing object.<br><br>So again, why should =
we go against how all other objects in the standard work? You've proven to =
yourself that such an implementation <i>can</i> work and <i>can</i> be usef=
ul. That's great. But that's not enough to say that it <i>should</i> be don=
e, or that it should become <i>standardized</i>.</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_1471_22875935.1371324396616--
.
Author: carrierandoperator@yahoo.co.uk
Date: Sat, 15 Jun 2013 17:21:58 -0700 (PDT)
Raw View
------=_Part_2438_17065667.1371342118790
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
On Saturday, June 15, 2013 3:26:36 PM UTC-4, Nicol Bolas wrote:
>
> On Friday, June 14, 2013 4:22:28 PM UTC-7, carrieran...@yahoo.co.uk wrote=
:
>>
>> On Friday, June 14, 2013 10:11:07 AM UTC-4, Alex B wrote:
>>>
>>>
>>> 3. Why impose that size > 0 ?
>>>
>>
>> In my implementation, empty sequences are forbidden. That is by design.=
=20
>> I've lived with this constraint in my implementation for years and have =
no=20
>> desire or need to permit empty sequences in that implementation. I don't=
=20
>> consider it a nuisance, but an aid. It increases memory safety, and=20
>> provides narrow semantics similar to references.
>>
>> Because I found reference-like semantics were adequate (a _feature_, in=
=20
>> fact), I decided to also apply them to this proposed type. And yes, I=20
>> figured there would be resistance to that idea. And yes, I am willing to=
=20
>> lift that restriction if a majority says they favor empty sequences=20
>> (ideally, that would be demonstrated by examples of why they really are=
=20
>> necessary). After all, the implementation is for everybody rather than f=
or=20
>> my needs. Another possibile approach would be to make that condition a=
=20
>> template parameter. I don't find that necessary=85 but if it is the majo=
r=20
>> halting point, then I will consider such changes.
>>
>> So I've proven to myself that reference-like semantics are possible and=
=20
>> regard them to be very beneficial, but they aren't something you could=
=20
>> introduce after the fact without breaking changes so now is the appropri=
ate=20
>> time to push for them.
>>
>> The route I am taking is (if this gains traction) to provide an=20
>> implementation where either:
>>
>> 1. reference-like semantics are enforced or
>> 2. members will not be const (and empty is permitted).
>> =20
>>
>> Then people can play with it and see for themselves how much of a=20
>> nuisance an approach really is. But I do realize that it does remove=20
>> capabilities people are accustomed to having and that it's a pretty big =
*
>> change* from what many are used to. I've found that change is a good=20
>> one, but I know some will disagree or say they see no great benefit in=
=20
>> narrowing the capabilities of a pointer+size. The ability to use pointer=
=20
>> and size isn't going to be removed. Iterators and range implementations=
=20
>> won't disappear. It's just another tool in the toolbox. It does not atte=
mpt=20
>> to solve everything which can be accomplished with a pointer and size.=
=20
>> Rather, sequences attempt to solve a very narrow problem, without=20
>> introducing complexities (or functionality) found in types like iterator=
or=20
>> range implementations. Creating an object which focuses on the essence o=
f a=20
>> problem is a fine ideal.
>>
>> Note: When I write "my implementation", I mean the implementation that I=
=20
>> wrote and exists in my codebase -- not identical to the result of this=
=20
>> proposal (if that materializes).
>>
>
> I'm in total agreement with Nevin on this: this is a complete deal-breake=
r.
>
> What is the most common operation performed on an arbitrary range of=20
> contiguously-allocated elements? Iteration=85<snip>
>
I've said it in multiple ways, including in the text you quoted: *A=20
sequence is not an iterator.*
=20
> So your non-empty "sequence" reference would be the odd man out.
>
You've miscategorized it. Treating a sequence as an iterator is as equally=
=20
flawed as:
// WRONG
std::unique_ptr<int> a(new int(1));
std::unique_ptr<int> b(new int(2));
auto ret(std::find(a, b, 2));
- or -
std::vector<int> a(1, 2);
std::vector<int> b(3, 4);
auto ret(std::find(a, b, 2));
Think of it this way, instead:
// RIGHT
std::vector<int> a(1, 2);
auto ra(std::find(a.begin(), a.end(), 2));
std::sequence<int> b(a);
auto rb(std::find(b.begin(), b.end(), 2));
Sequences *provide* iterators, but they themselves are not iterators. So=20
you can still use it with `for (auto e:sq)`, like a vector<> or array<>.
=20
> It also serves to make code needlessly obtuse. Take this function for=20
> example:
>
> void func(std::sequence sq)
> {
> if(sq.size() > 0)
> return;
>
> auto pair =3D sq.divide(1);
> process_ranges(pair);
> }
>
> OK, what's in `pair`? The way you want it, it would contain a sequence of=
=20
> one element and a sequence that *may or may not* be a legitimate value.=
=20
> You can't even *ask* it if it is a legitimate sequence. Indeed, simply=20
> calling `sq.divide(1)` on a range that doesn't have more than one element=
=20
> may result in undefined behavior.
>
Even if the sequence were allowed to be empty, it's either undefined or=20
would throw. There are some pretty obvious logic errors here. This is what=
=20
your program asks: If the sequence is not empty, return. Otherwise, give me=
=20
one sequence representing the zeroeth element of that empty sequence and=20
give me another sequence which represents all elements after the zeroeth.
=20
> Why? I already checked that there was at least one value. Are you saying =
I=20
> should have to do this:
>
> void func(std::sequence sq)
> {
> if(sq.size() > 0)
> return;
>
> if(sq.size() > 1)
> {
> auto pair =3D sq.divide(1);
> process_ranges(pair);
> }
>
> process_first_range(sq);
> }
>
> What good is that? I now have to split my `process_ranges` function into=
=20
> two, one that takes two ranges and one that just takes one. The original=
=20
> `process_ranges` function *could have probably* worked just fine with=20
> empty ranges. But because of a completely arbitrary design limitation, my=
=20
> code has to be split.
>
Emphasis mine. I covered this problem in quite a bit of detail in the post=
=20
you responded to. But I think this bit is worth repeating in light of your=
=20
example: *"It localizes that logic and error to precisely where it needs to=
=20
be, forbidding the error from propagating (or continuing in a defined=20
manner).".* These are _your_ logic errors to fix (or possibly upstream),=20
not for `process_*` functions to defend itself from:
1. You test a sequence `sq` and return if not empty. When empty=20
sequences are prohibited, the test is not necessary. Furthermore, it's t=
he=20
caller's responsibility to pass a valid sequence (i.e. which is not empt=
y).=20
Either you know the answer or it is unreachable in a defined manner.=20
2. The non-empty provision saves you from the logic bug you wrote (if=20
(sq.size() > 0) return;). You don't need to bother testing that the=20
sequence is empty if it is forbidden from being empty (simply omit those=
=20
lines). So if the sequence were allowed to be empty, then yes, you tend =
to=20
see precondition tests and bugs like this at the start of many, many=20
functions.
3. Why should you trust that the client permits you to call functions=20
with 'null' parameters? Sure, it makes sense to react to absence in some=
=20
cases (e.g. along another path) but when you ask it to "process" an zero=
=20
length array's elements and assume it "could have probably worked just=
=20
fine" there are a few issues. a) What sense does it make to create an em=
pty=20
range and request it to be "processed"? b) If process_*() takes sequence=
s=20
as parameters, then that means it is your logic error if you attempt to=
=20
pass an empty sequence. c) Don't assume it "could have probably worked j=
ust=20
fine" or have no undesirable side-effects. That's still a logic error, a=
nd=20
these types of errors are best caught at the point they are introduced.=
=20
That just pushes validation into the process function -- now it needs to=
=20
specify how it will respond if it is asked to process nothing: Will it=
=20
throw? Will it abort? Is it undefined? Is it unspecified? Now implement =
it=20
accordingly so that it handles those conditions. If it specifies a seque=
nce=20
(or pair of), then that means that it's an error to ask that it processe=
s=20
nothing. The function does not need to add all that documentation and er=
ror=20
detection because the sequence uses reference-like semantics (being=20
prepared to handle any scenario is usually going to fatten and slow your=
=20
programs). Nor does it need to handle the empty case. This hoists a ton =
of=20
error detection out of the process function(s). If absence is permitted,=
=20
then you still have the option to declare a parameter of another type.
Nevertheless, I understand the intent of the sample. So the corrected=20
example is:
void func(std::sequence<int> sq) {
if (sq.size() =3D=3D 1) {
process_first_range(sq);
}
else {
process_ranges(sq.divide(1));
}
}
Sure, you _could_ do that. But the problem you are trying to solve is still=
=20
of the mindset that a sequence is an iterator or range -- when it's=20
neither. So I don't regard it as good example. Real examples are better.
So an actual implementation might take the form:
void func(std::sequence<int> sq) {
process(sq);
}
or
void func(std::sequence<int> sq) {
for (auto& at:sq)
process(at);
}
or you might instead pass iterators, your favorite range implementation,=20
slice the sequence, or use a more obvious syntax to denote an optional=20
parameter -- depending on what exactly you are trying to accomplish.=20
Chances are good, there's a clearer way to structure the program. Sequences=
=20
don't need to handle _every_ role regarding the possible ways one could=20
approach this problem.
But yes, introducing logic _can_ complicate portions of the program.=20
Guarantees (e.g. reference-like semantics) also greatly simplify many=20
aspects of your program. It's a tradeoff, and you need to decide what is=20
the right tool for the problem you are trying to solve. *Then* you can=20
achieve a good balance of correctness, expressiveness, and syntactical=20
convenience. With objects, references are typically favored over pointers=
=20
although restrictions of references can make pointers a more appropriate or=
=20
necessary tool. If you use sequences in the right places, then it=20
simplifies a lot of your code, much like references have become used in=20
more places than pointers (in C++ programs).
=20
> The only justification you've put forth for this is that you want the=20
> class to have "reference semantics" and references can't be empty. But ev=
en=20
> that is specious. A reference cannot be *invalid*. An empty sequence is=
=20
> still a *valid sequence*, just like the empty set<http://en.wikipedia.org=
/wiki/Empty_set>is still a valid set. You may not be able to get anything f=
rom it, but=20
> there are plenty of valid uses for an empty sequence. `begin/end` may not=
=20
> return valid iterators, but they are required to return the *same*iterato=
r value, and thus you can iterate over them.
>
It's not an iterator. I have been using reference-like semantics for years=
=20
with this type and it plays out very nicely. I've also said that there will=
=20
be modes where that restriction may be lifted in an demo implementation. So=
=20
I have already sympathized to objections to reference-like semantics.
=20
> So why should we go against *decades* of user experience here?
>
Let's not overstate -- References were introduced 30 years ago.
=20
> And speaking of decades of experience, that applies to the whole=20
> "immutable reference semantics" thing too. Pretty much every object in th=
e=20
> C++ standard library since C++98 uses *value* semantics. Even the=20
> istreams work by value-move; they just forbid copying. They're mutable by=
=20
> default; if you want them to be immutable, you make them `const`. That's=
=20
> the *standard*.
>
> The only objects that don't use pure value semantics are those that=20
> explicitly reference things. And even those are by-*value* references:=20
> std::reference_wrapper can be re-seated, as can std::shared_ptr, and any=
=20
> other standard library reference-to-thing object.
>
> So again, why should we go against how all other objects in the standard=
=20
> work? You've proven to yourself that such an implementation *can* work=20
> and *can* be useful. That's great. But that's not enough to say that it *
> should* be done, or that it should become *standardized*.
>
=20
And I acknowledged that I expected resistance to the idea of reference-like=
=20
semantics, and was offered to put out an implementation which supports both=
=20
modes. We'll have to wait and see how it goes.
Thanks for the feedback.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2438_17065667.1371342118790
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
<br><br>On Saturday, June 15, 2013 3:26:36 PM UTC-4, Nicol Bolas wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;">On Friday, June 14, 2013 4:22:28 P=
M UTC-7, <a>carrieran...@yahoo.co.uk</a> wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex">On Friday, June 14, 2013 10:11:07 AM UTC-4, Alex B wrote:<block=
quote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex"><div><br></div><div>3. Why impose that si=
ze > 0 ?</div></blockquote><div><br></div><div>In my implementation, emp=
ty sequences are forbidden. That is by design. I've lived with this constra=
int in my implementation for years and have no desire or need to permit emp=
ty sequences in that implementation. I don't consider it a nuisance, but an=
aid. It increases memory safety, and provides narrow semantics similar to =
references.</div><div><br></div><div>Because I found reference-like semanti=
cs were adequate (a _feature_, in fact), I decided to also apply them to th=
is proposed type. And yes, I figured there would be resistance to that idea=
.. And yes, I am willing to lift that restriction if a majority says they fa=
vor empty sequences (ideally, that would be demonstrated by examples of why=
they really are necessary). After all, the implementation is for everybody=
rather than for my needs. Another possibile approach would be to make that=
condition a template parameter. I don't find that necessary=85 but if it i=
s the major halting point, then I will consider such changes.</div><div><br=
></div><div>So I've proven to myself that reference-like semantics are poss=
ible and regard them to be very beneficial, but they aren't something you c=
ould introduce after the fact without breaking changes so now is the approp=
riate time to push for them.</div><div><br></div><div>The route I am taking=
is (if this gains traction) to provide an implementation where either:</di=
v><div><ol><li>reference-like semantics are enforced or<br></li><li>members=
will not be const (and empty is permitted).<br></li></ol></div><div><br></=
div><div>Then people can play with it and see for themselves how much of a =
nuisance an approach really is. But I do realize that it does remove capabi=
lities people are accustomed to having and that it's a pretty big <b>change=
</b> from what many are used to. I've found that change is a good one, but =
I know some will disagree or say they see no great benefit in narrowing the=
capabilities of a pointer+size. The ability to use pointer and size isn't =
going to be removed. Iterators and range implementations won't disappear. I=
t's just another tool in the toolbox. It does not attempt to solve everythi=
ng which can be accomplished with a pointer and size. Rather, sequences att=
empt to solve a very narrow problem, without introducing complexities (or f=
unctionality) found in types like iterator or range implementations. Creati=
ng an object which focuses on the essence of a problem is a fine ideal.</di=
v><div><br></div><div>Note: When I write "my implementation", I mean the im=
plementation that I wrote and exists in my codebase -- not identical to the=
result of this proposal (if that materializes).</div></blockquote><div><br=
>I'm in total agreement with Nevin on this: this is a complete deal-breaker=
..<br><br>What is the most common operation performed on an arbitrary range =
of contiguously-allocated elements? Iteration=85<snip><br></div></blo=
ckquote><div><br></div><div>I've said it in multiple ways, including in the=
text you quoted: <b>A sequence is not an iterator.</b></div><div> </d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;=
border-left: 1px #ccc solid;padding-left: 1ex;"><div>So your non-empty "seq=
uence" reference would be the odd man out.<br></div></blockquote><div><br><=
/div><div>You've miscategorized it. Treating a sequence as an iterator is a=
s equally flawed as:</div><div><br></div><div><div></div></div><div style=
=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 1=
87); word-wrap: break-word; " class=3D"prettyprint"><code class=3D"prettypr=
int"><div class=3D"subprettyprint"><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">// WRONG</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br> std</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">unique_ptr</span><span style=3D"color: #080;" class=3D"styled-by=
-prettify"><int></span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> a</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">new</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">));</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> std</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">unique_ptr</span><span style=3D"color: #080;" class=3D"s=
tyled-by-prettify"><int></span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">new</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #066;" class=3D"styled-by-prettify">2</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">));</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br> </span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> ret</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">find<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">a</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> b</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styled-b=
y-prettify">2</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">));</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">-</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">or</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">-</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br> std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">vector</span><span style=3D"color: #080;" class=3D"styled-b=
y-prettify"><int></span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> a</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">(</span><span style=3D"color: #066;" class=3D"styled-by-prettify">1</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #066;" class=3D"styled-by-prettify">2</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br> std</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">vector</span><span style=3D"color: #080;" class=3D"=
styled-by-prettify"><int></span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #066;" class=3D"styled-by-pretti=
fy">3</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #066;" class=3D"styled-by-prettify">4</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br> </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> ret</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
find</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">a</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> b</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"styl=
ed-by-prettify">2</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">));</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span></div></code></div><div><br></div><div>Think of it this way, ins=
tead:</div><div><br></div><div><div style=3D"background-color: rgb(250, 250=
, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break-word; " clas=
s=3D"prettyprint"><code class=3D"prettyprint"><span class=3D"styled-by-pret=
tify" style=3D"color: rgb(0, 0, 0); ">// RIGHT<br> std</span><span cla=
ss=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0); ">::</span><spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0); ">vector</span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 136, 0); "><i=
nt></span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0=
); "> a</span><span class=3D"styled-by-prettify" style=3D"color: rgb(1=
02, 102, 0); ">(</span><span class=3D"styled-by-prettify" style=3D"color: r=
gb(0, 102, 102); ">1</span><span class=3D"styled-by-prettify" style=3D"colo=
r: rgb(102, 102, 0); ">,</span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(0, 0, 0); "> </span><span class=3D"styled-by-prettify" styl=
e=3D"color: rgb(0, 102, 102); ">2</span><span class=3D"styled-by-prettify" =
style=3D"color: rgb(102, 102, 0); ">);</span><span class=3D"styled-by-prett=
ify" style=3D"color: rgb(0, 0, 0); "><br> </span><span class=3D"styled=
-by-prettify" style=3D"color: rgb(0, 0, 136); ">auto</span><span class=3D"s=
tyled-by-prettify" style=3D"color: rgb(0, 0, 0); "> ra</span><span cla=
ss=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0); ">(</span><span=
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0); ">std</span><sp=
an class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0); ">::</spa=
n><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0); ">find</=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0); "=
>(</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0); "=
>a</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0=
); ">.</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 1=
36); ">begin</span><span class=3D"styled-by-prettify" style=3D"color: rgb(1=
02, 102, 0); ">(),</span><span class=3D"styled-by-prettify" style=3D"color:=
rgb(0, 0, 0); "> a</span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(102, 102, 0); ">.</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 136); ">end</span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(102, 102, 0); ">(),</span><span class=3D"styled-by-prett=
ify" style=3D"color: rgb(0, 0, 0); "> </span><span class=3D"styled-by-=
prettify" style=3D"color: rgb(0, 102, 102); ">2</span><span class=3D"styled=
-by-prettify" style=3D"color: rgb(102, 102, 0); ">));</span><span class=3D"=
styled-by-prettify" style=3D"color: rgb(0, 0, 0); "><br></span><div class=
=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br> std</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">se=
quence</span><span style=3D"color: #080;" class=3D"styled-by-prettify"><=
int></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><fo=
nt color=3D"#006666"><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">a</span></font><span style=3D"color: #660;" class=3D"styled-by-prettify=
">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&n=
bsp;</span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> rb</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">find</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">b</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">.</span><span style=3D"color: #008;" class=3D"styled-by-prettify">b=
egin</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(),</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">end</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(),</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=
=3D"styled-by-prettify">2</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">));</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br><br></span></div></code></div><div><br></div><div>Sequences *pr=
ovide* iterators, but they themselves are not iterators. So you can still u=
se it with `for (auto e:sq)`, like a vector<> or array<>.<br><b=
r></div><br></div><div> </div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div>It also serves to make code needlessly obtuse. Take this functio=
n for example:<br><br><div style=3D"background-color:rgb(250,250,250);borde=
r-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:brea=
k-word"><code><div><span style=3D"color:#008">void</span><span style=3D"col=
or:#000"> func</span><span style=3D"color:#660">(</span><span style=3D"colo=
r:#000">std</span><span style=3D"color:#660">::</span><span style=3D"color:=
#000">sequence sq</span><span style=3D"color:#660">)</span><span style=3D"c=
olor:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"col=
or:#000"><br> </span><span style=3D"color:#008">if</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">sq</span><span style=3D"=
color:#660">.</span><span style=3D"color:#000">size</span><span style=3D"co=
lor:#660">()</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">></span><span style=3D"color:#000"> </span><span style=3D"color:#0=
66">0</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><=
br> </span><span style=3D"color:#008">return</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br><br> </span><s=
pan style=3D"color:#008">auto</span><span style=3D"color:#000"> pair </span=
><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> sq</span>=
<span style=3D"color:#660">.</span><span style=3D"color:#000">divide</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#066">1</span><span=
style=3D"color:#660">);</span><span style=3D"color:#000"><br> proces=
s_ranges</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">pair</span><span style=3D"color:#660">);</span><span style=3D"color:#000"=
><br></span><span style=3D"color:#660">}</span></div></code></div><br>OK, w=
hat's in `pair`? The way you want it, it would contain a sequence of o=
ne element and a sequence that <i>may or may not</i> be a legitimate value.=
You can't even <i>ask</i> it if it is a legitimate sequence. Indeed, simpl=
y calling `sq.divide(1)` on a range that doesn't have more than one element=
may result in undefined behavior.</div></blockquote><div><br></div><div>Ev=
en if the sequence were allowed to be empty, it's either undefined or would=
throw. There are some pretty obvious logic errors here. This is what your =
program asks: If the sequence is not empty, return. Otherwise, give me one =
sequence representing the zeroeth element of that empty sequence and give m=
e another sequence which represents all elements after the zeroeth.</div><d=
iv><br></div><div><br></div><div> </div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div>Why? I already checked that there was at least one valu=
e. Are you saying I should have to do this:<br><br><div style=3D"background=
-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bo=
rder-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">=
void</span><span style=3D"color:#000"> func</span><span style=3D"color:#660=
">(</span><span style=3D"color:#000">std</span><span style=3D"color:#660">:=
:</span><span style=3D"color:#000">sequence sq</span><span style=3D"color:#=
660">)</span><span style=3D"color:#000"><br></span><span style=3D"color:#66=
0">{</span><span style=3D"color:#000"><br> </span><span style=3D"colo=
r:#008">if</span><span style=3D"color:#660">(</span><span style=3D"color:#0=
00">sq</span><span style=3D"color:#660">.</span><span style=3D"color:#000">=
size</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">></span><span style=3D"color:#000"> </=
span><span style=3D"color:#066">0</span><span style=3D"color:#660">)</span>=
<span style=3D"color:#000"><br> </span><span style=3D"color:#0=
08">return</span><span style=3D"color:#660">;</span><span style=3D"color:#0=
00"><br><br> </span><span style=3D"color:#008">if</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">sq</span><span style=3D"=
color:#660">.</span><span style=3D"color:#000">size</span><span style=3D"co=
lor:#660">()</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">></span><span style=3D"color:#000"> </span><span style=3D"color:#0=
66">1</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><=
br> </span><span style=3D"color:#660">{</span><span style=3D"color:#0=
00"><br> </span><span style=3D"color:#008">auto</span><span st=
yle=3D"color:#000"> pair </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> sq</span><span style=3D"color:#660">.</span><span sty=
le=3D"color:#000">divide</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#066">1</span><span style=3D"color:#660">);</span><span style=
=3D"color:#000"><br> process_ranges</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">pair</span><span style=3D"color:#=
660">);</span><span style=3D"color:#000"><br> </span><span style=3D"c=
olor:#660">}</span><span style=3D"color:#000"><br><br> process_first_=
range</span><span style=3D"color:#660">(</span><span style=3D"color:#000">s=
q</span><span style=3D"color:#660">);</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></=
span></div></code></div><br>What good is that? I now have to split my `proc=
ess_ranges` function into two, one that takes two ranges and one that just =
takes one. The original `process_ranges` function <b><u>could have probably=
</u></b> worked just fine with empty ranges. But because of a completely ar=
bitrary design limitation, my code has to be split.<br></div></blockquote><=
div><br></div><div>Emphasis mine. I covered this problem in quite a bit of =
detail in the post you responded to. But I think this bit is worth repeatin=
g in light of your example: <i>"It localizes that logic and error to p=
recisely where it needs to be, forbidding the error from propagating (or co=
ntinuing in a defined manner).".</i> These are _your_ logic errors to fix (=
or possibly upstream), not for `process_*` functions to defend itself from:=
</div><div><ol><li>You test a sequence `sq` and return if not empty. When e=
mpty sequences are prohibited, the test is not necessary. Furthermore, it's=
the caller's responsibility to pass a valid sequence (i.e. which is not em=
pty). Either you know the answer or it is unreachable in a defined manner.&=
nbsp;<br></li><li>The non-empty provision saves you from the logic bug you =
wrote (if (sq.size() > 0) return;). You don't need to bother testing tha=
t the sequence is empty if it is forbidden from being empty (simply omit th=
ose lines). So if the sequence were allowed to be empty, then yes, you tend=
to see precondition tests and bugs like this at the start of many, many fu=
nctions.<br></li><li>Why should you trust that the client permits you to ca=
ll functions with 'null' parameters? Sure, it makes sense to react to absen=
ce in some cases (e.g. along another path) but when you ask it to "process"=
an zero length array's elements and assume it "could have probably worked =
just fine" there are a few issues. a) What sense does it make to create an =
empty range and request it to be "processed"? b) If process_*() takes seque=
nces as parameters, then that means it is your logic error if you attempt t=
o pass an empty sequence. c) Don't assume it "could have probably worked ju=
st fine" or have no undesirable side-effects. That's still a logic error, a=
nd these types of errors are best caught at the point they are introduced. =
That just pushes validation into the process function -- now it needs to sp=
ecify how it will respond if it is asked to process nothing: Will it throw?=
Will it abort? Is it undefined? Is it unspecified? Now implement it accord=
ingly so that it handles those conditions. If it specifies a sequence (or p=
air of), then that means that it's an error to ask that it processes nothin=
g. The function does not need to add all that documentation and error detec=
tion because the sequence uses reference-like semantics (being prepared to =
handle any scenario is usually going to fatten and slow your programs). Nor=
does it need to handle the empty case. This hoists a ton of error detectio=
n out of the process function(s). If absence is permitted, then you still h=
ave the option to declare a parameter of another type.</li></ol></div><div>=
Nevertheless, I understand the intent of the sample. So the corrected =
example is:</div><div><br></div><div style=3D"background-color: rgb(250, 25=
0, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break-word; " cla=
ss=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint=
"><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> func</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">sequence</span><span style=3D"color: #080;" class=
=3D"styled-by-prettify"><int></span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> sq</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">)</span><font color=3D"#000000"><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span></font><span style=3D"color: #660;=
" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">if</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">sq=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">size</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">()</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">=3D=3D</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=3D"=
styled-by-prettify">1</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> proce=
ss_first_range</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">sq</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">else</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> process_ranges</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">sq</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">divide</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">(</span><span style=3D"color: #066;" class=3D"styled-by-prettify=
">1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">));</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><div><b=
r></div><div>Sure, you _could_ do that. But the problem you are trying=
to solve is still of the mindset that a sequence is an iterator or range -=
- when it's neither. So I don't regard it as good example. Real exampl=
es are better.</div><div><br></div><div>So an actual implementation might t=
ake the form:</div><div><br></div><div><div style=3D"background-color: rgb(=
250, 250, 250); border: 1px solid rgb(187, 187, 187); word-wrap: break-word=
; " class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subpret=
typrint"><span style=3D"color: #008;" class=3D"styled-by-prettify">void</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> func</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">sequence</span><span style=3D"color: #080;"=
class=3D"styled-by-prettify"><int></span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> sq</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
> process</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">sq</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></code></div>=
<div><br></div></div><div>or</div><div><br></div><div><div style=3D"backgro=
und-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 187); word-w=
rap: break-word; " class=3D"prettyprint"><code class=3D"prettyprint"><div c=
lass=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> func</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">sequence</span><span style=
=3D"color: #080;" class=3D"styled-by-prettify"><int></span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> sq</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">for</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">&</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> at</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">sq</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br> process</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">at</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
</div></code></div><br>or you might instead pass iterators, your favorite r=
ange implementation, slice the sequence, or use a more obvious syntax to de=
note an optional parameter -- depending on what exactly you are trying to a=
ccomplish. Chances are good, there's a clearer way to structure the program=
.. Sequences don't need to handle _every_ role regarding the possible ways o=
ne could approach this problem.</div><div><br></div><div>But yes, introduci=
ng logic _can_ complicate portions of the program. Guarantees (e.g. referen=
ce-like semantics) also greatly simplify many aspects of your program. It's=
a tradeoff, and you need to decide what is the right tool for the problem =
you are trying to solve. *Then* you can achieve a good balance of correctne=
ss, expressiveness, and syntactical convenience. With objects, references a=
re typically favored over pointers although restrictions of references can =
make pointers a more appropriate or necessary tool. If you use sequences in=
the right places, then it simplifies a lot of your code, much like referen=
ces have become used in more places than pointers (in C++ programs).</div><=
div><br></div><div> </div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div>The only justification you've put forth for this is that you want the=
class to have "reference semantics" and references can't be empty. But eve=
n that is specious. A reference cannot be <i>invalid</i>. An empty sequence=
is still a <i>valid sequence</i>, just like the <a href=3D"http://en.wikip=
edia.org/wiki/Empty_set" target=3D"_blank">empty set</a> is still a valid s=
et. You may not be able to get anything from it, but there are plenty of va=
lid uses for an empty sequence. `begin/end` may not return valid iterators,=
but they are required to return the <i>same</i> iterator value, and thus y=
ou can iterate over them.<br></div></blockquote><div><br></div><div>It's no=
t an iterator. I have been using reference-like semantics for years with th=
is type and it plays out very nicely. I've also said that there will be mod=
es where that restriction may be lifted in an demo implementation. So I hav=
e already sympathized to objections to reference-like semantics.</div><div>=
<br></div><div> </div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v>So why should we go against <i>decades</i> of user experience here?<br></=
div></blockquote><div><br></div><div>Let's not overstate -- References were=
introduced 30 years ago.</div><div><br></div><div> </div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div>And speaking of decades of experience=
, that applies to the whole "immutable reference semantics" thing too. Pret=
ty much every object in the C++ standard library since C++98 uses <i>value<=
/i> semantics. Even the istreams work by value-move; they just forbid copyi=
ng. They're mutable by default; if you want them to be immutable, you make =
them `const`. That's the <i>standard</i>.<br><br>The only objects that don'=
t use pure value semantics are those that explicitly reference things. And =
even those are by-<i>value</i> references: std::reference_wrapper can be re=
-seated, as can std::shared_ptr, and any other standard library reference-t=
o-thing object.<br><br>So again, why should we go against how all other obj=
ects in the standard work? You've proven to yourself that such an implement=
ation <i>can</i> work and <i>can</i> be useful. That's great. But that's no=
t enough to say that it <i>should</i> be done, or that it should become <i>=
standardized</i>.</div></blockquote><div> </div><div>And I acknowledge=
d that I expected resistance to the idea of reference-like semantics, and w=
as offered to put out an implementation which supports both modes. We'=
ll have to wait and see how it goes.</div><div><br></div><div>Thanks for th=
e feedback.</div><div><br></div><div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_2438_17065667.1371342118790--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 15 Jun 2013 19:55:24 -0700 (PDT)
Raw View
------=_Part_1635_8944719.1371351324158
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
OK, this is clearly coming down to a "religious" issue. You have come to=20
the belief that an empty "sequence" represents an invalid state comparable=
=20
to a NULL pointer. You therefore believe that any operation that generates=
=20
an empty sequence represents an erroneous operation. And therefore you=20
believe that your system should explicitly disallow this possibility.
The entire rest of the world disagrees with you. Virtually every API that=
=20
takes a sequence of contiguously allocated objects will accept an empty=20
sequence thereof, regardless of how that API might define an empty sequence=
..
Be that as it may, if you wish to persist with this notion that "empty =3D=
=3D=20
invalid =3D=3D error", then you need to be *serious* about it. And that mea=
ns=20
you *need* to throw an exception on any circumstance that would result in=
=20
an empty range. Merely being "undefined behavior" isn't enough, even by=20
your own standard:
It localizes that logic and error to precisely where it needs to be,=20
> forbidding the error from propagating (or continuing in a defined manner)=
..
>
Even if we assume that generating an empty range is a logic error, you=20
can't *forbid* a logic error if you allow the program to continue. Calling=
=20
it "undefined" is objectively *worse* than either throwing or allowing=20
sequences to be empty.
If sequences could be empty, then algorithms that could break on empty=20
sequences could be written *defensively* and thus check for them and return=
=20
appropriate values (see every C/C++ function that takes a range). And if=20
operations that produce empty sequences throw, then it is very easy to=20
track down exactly who's responsible for the empty sequence, since it would=
=20
throw an exception at the moment of creation.
By making it undefined, you get the *worst* of both worlds: you can't write=
=20
defensively against undefined behavior, and you can't guarantee you get the=
=20
actual program break in the place where the brokenness *originated*.
Now, let me head off the incoming "perfidy" argument, that C++ doesn't=20
protect users from *willful* misuse, only accidental misuse. For example,=
=20
there's nothing in C++ that allows you to defend a function from a "null=20
reference" either.
However, there's a big difference between a null reference and this: namely=
=20
in how hard it is to screw it up.
It's actually rather difficult to create a null reference *by accident* in=
=20
C++; you pretty much have to be *trying* to do it. To generate one that,=20
you must at some point in your code take a pointer (which you haven't=20
checked against NULL) and do this with it: `T &t =3D *ptr;`.
That's always suspect code. And it's generally pretty easy to track down=20
where and when that could happen, especially if direct, naked pointer use=
=20
in your program is rare.
By contrast, an empty sequence is *very* easy to create. It's as simple as=
=20
this:
void func(sequence<int> seq);
vector<int> v;
//Lots of arbitrary code that does *not* fill in `v`.
func(v);
This *looks* like perfectly legitimate code. If someone were doing a code=
=20
review of it, it would seem on the surface to be reasonable. It's only not=
=20
reasonable because of the limitations of sequence. Which, as previously=20
established, go against every expectation of most C/C++ APIs. Which also=20
means that it goes against the expectations of most C/C++ *programmers*. So=
=20
most programmers will look at this code and expect it to work.
The way you want to do things, *every time* the user wants to take a=20
concrete container and make a sequence out of it, they have to either check=
=20
for emptiness or be in a place where they can be assured that the container=
=20
isn't empty. It is *very* easy to get it wrong, and if they do... boom. But=
=20
not a loud boom.
It's silent, but deadly.
Errors that are easy to do should be *noisy*, not silent.
Furthermore, you said:
But the problem you are trying to solve is still of the mindset that a=20
> sequence is an iterator or range -- when it's neither.
>
Perhaps that is because you have not provided a proper *conceptual*foundati=
on for what you're proposing. The C++ standard defines what an=20
"iterator" is, conceptually. There's an informal understanding among C++=20
programmers what a "range" is.
If you're proposing some new conceptual idea that is distinct from other=20
ideas, then you first need to *define* it. And you haven't. You've defined=
=20
what the classes *do*, but not what they *mean* on a conceptual level.
An InputIterator has some specific interface, but it also has a conceptual=
=20
meaning. It's an abstract, single-pass interface for extracting values from=
=20
an ordered sequence of values (this is also another reason to avoid the=20
"sequence" wording, because the standard already has things called=20
"sequences"). We need some kind of conceptual foundation for these objects=
=20
that helps explain and justify the design.
And when you're defining these "sequences" conceptually, you should also=20
answer questions like these:
Why is it *not* a range? Why have you defined it conceptually in such a way=
=20
that it doesn't qualify as a range? What part of ranges are you trying to=
=20
"fix" with this concept? What part of the concept *requires* it to not be=
=20
empty? Is that an essential element of the concept?
And if it's true that "Sequences don't need to handle _every_ role=20
regarding the possible ways one could approach this problem," why should we=
=20
have them at all if there is a concept that *can* "handle every role" and=
=20
allow us to solve problems more effectively?
On Saturday, June 15, 2013 5:21:58 PM UTC-7, carrieran...@yahoo.co.uk wrote=
:
>
> On Saturday, June 15, 2013 3:26:36 PM UTC-4, Nicol Bolas wrote:
>>
>> I'm in total agreement with Nevin on this: this is a complete=20
>> deal-breaker.
>>
>> What is the most common operation performed on an arbitrary range of=20
>> contiguously-allocated elements? Iteration=85<snip>
>>
>
> I've said it in multiple ways, including in the text you quoted: *A=20
> sequence is not an iterator.*
>
You're right, sequences aren't iterators.
But I never said that they were, so your statement is a non-sequitur. I=20
said that the most common operation that someone would perform on a=20
sequence would be *iteration*, but iteration does not require or even imply=
=20
the use of an iterator. The most common operation people do on a `vector`=
=20
or array is iteration too; that doesn't make them iterators.
So I don't regard it as good example. Real examples are better.
>
> So an actual implementation might take the form:
>
> void func(std::sequence<int> sq) {
> process(sq);
> }
>
> or
>
> void func(std::sequence<int> sq) {
> for (auto& at:sq)
> process(at);
> }
>
>
The problem with these "solutions" is that they don't actually solve the=20
problem; not the problem that was outlined. The original example code very=
=20
clearly stated that `process` took *two sequences*. The sole purpose of=20
`func` was therefore to split a single sequence arbitrarily for consumption=
=20
by `process`.
Since your examples don't actually do the same thing, they're invalid=20
solutions to the problem at hand.
So why should we go against *decades* of user experience here?
>>
>
> Let's not overstate -- References were introduced 30 years ago.
>
And yet, virtually every C++ object has value semantics. Imagine that;=20
after 30 years, we're still using objects with value semantics.
Furthermore, my comment was in response to the lack of a valid empty state,=
=20
not to your by-reference reference* semantics. These are in fact separate=
=20
issues; you can still have your by-reference reference semantics while=20
defining the empty state as valid.
*: Not a typo. "By-reference reference" means that the object functions=20
like a C++ reference (thus "by-reference"), and the object conceptually=20
acts as a reference to another object (the second "reference") that it does=
=20
not own. This is to distinguish your "sequence" type from "by-value=20
reference" types like `shared_ptr`. There, the object itself works by value=
=20
(you can assign to it), but the object acts as a reference to another=20
object that it does not (fully) own.
And speaking of decades of experience, that applies to the whole "immutable=
=20
>> reference semantics" thing too. Pretty much every object in the C++=20
>> standard library since C++98 uses *value* semantics. Even the istreams=
=20
>> work by value-move; they just forbid copying. They're mutable by default=
;=20
>> if you want them to be immutable, you make them `const`. That's the *
>> standard*.
>>
>> The only objects that don't use pure value semantics are those that=20
>> explicitly reference things. And even those are by-*value* references:=
=20
>> std::reference_wrapper can be re-seated, as can std::shared_ptr, and any=
=20
>> other standard library reference-to-thing object.
>>
>> So again, why should we go against how all other objects in the standard=
=20
>> work? You've proven to yourself that such an implementation *can* work=
=20
>> and *can* be useful. That's great. But that's not enough to say that it =
*
>> should* be done, or that it should become *standardized*.
>>
> =20
> And I acknowledged that I expected resistance to the idea of=20
> reference-like semantics, and was offered to put out an implementation=20
> which supports both modes. We'll have to wait and see how it goes.
>
My ultimate point here is this: If you take those out, your proposal is no=
=20
different from `array_ref` besides the name. So why would yours succeed=20
where array_ref failed?
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1635_8944719.1371351324158
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
OK, this is clearly coming down to a "religious" issue. You have come to
the belief that an empty "sequence" represents an invalid state=20
comparable to a NULL pointer. You therefore believe that any operation that=
generates an empty sequence represents an erroneous operation. And therefo=
re you believe that your system
should explicitly disallow this possibility.<br><br>The entire rest of the=
world disagrees with=20
you. Virtually every API that takes a sequence of contiguously allocated ob=
jects will accept an empty sequence thereof, regardless of how that API mig=
ht define an empty sequence.<br><br>Be that as it may, if you wish to persi=
st with this notion that "empty =3D=3D invalid =3D=3D error", then you need=
to be <i>serious</i> about it. And that means you <i>need</i> to throw an =
exception on any circumstance that would result in an empty range. Merely b=
eing "undefined behavior" isn't enough, even by your own standard:<br><br><=
blockquote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(2=
04, 204, 204); padding-left: 1ex;" class=3D"gmail_quote">It localizes that =
logic and error to precisely where it needs to be, forbidding the error fro=
m propagating (or continuing in a defined manner).<br></blockquote><br>Even=
if we assume that generating an empty range is a logic error, you can't <i=
>forbid</i> a logic error if you allow the program to continue. Calling it =
"undefined" is objectively <i>worse</i> than either throwing or allowing se=
quences to be empty.<br><br>If sequences could be empty, then algorithms th=
at could break on empty sequences could be written <i>defensively</i> and t=
hus check for them and return appropriate values (see every C/C++ function =
that takes a range). And if operations that produce empty sequences throw, =
then it is very easy to track down exactly who's responsible for the empty =
sequence, since it would throw an exception at the moment of creation.<br><=
br>By making it undefined, you get the <i>worst</i> of both worlds: you can=
't write defensively against undefined behavior, and you can't guarantee yo=
u get the actual program break in the place where the brokenness <i>origina=
ted</i>.<br><br>Now, let me head off the incoming "perfidy" argument, that =
C++ doesn't protect users from <i>willful</i> misuse, only accidental misus=
e. For example, there's nothing in C++ that allows you to defend a function=
from a "null reference" either.<br><br>However, there's a big difference b=
etween a null reference and this: namely in how hard it is to screw it up.<=
br><br>It's actually rather difficult to create a null reference <i>by acci=
dent</i> in C++; you pretty much have to be <i>trying</i> to do it. To gene=
rate one that, you must at some point in your code take a pointer (which yo=
u haven't checked against NULL) and do this with it: `T &t =3D *ptr;`.<=
br><br>That's always suspect code. And it's generally pretty easy to track =
down where and when that could happen, especially if direct, naked pointer =
use in your program is rare.<br><br>By contrast, an empty sequence is <i>ve=
ry</i> easy to create. It's as simple as this:<br><br><div class=3D"prettyp=
rint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187,=
187, 187); border-style: solid; border-width: 1px; word-wrap: break-word;"=
><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> func</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">sequence</span><span style=3D"color: #080;" class=
=3D"styled-by-prettify"><int></span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> seq</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br><br>vector</span><span style=3D"color: #080;" class=3D"style=
d-by-prettify"><int></span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> v</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br></span><span style=3D"color: #800;" class=3D"styled-by-prettify">//Lots =
of arbitrary code that does *not* fill in `v`.</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br>func</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">v</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">);</span></div></code></div><br>This <i>looks</i> like perf=
ectly legitimate code. If someone were doing a code review of it, it would =
seem on the surface to be reasonable. It's only not reasonable because of t=
he limitations of sequence. Which, as previously established, go against ev=
ery expectation of most C/C++ APIs. Which also means that it goes against t=
he expectations of most C/C++ <i>programmers</i>. So most programmers will =
look at this code and expect it to work.<br><br>The way you want to do thin=
gs, <i>every time</i> the user wants to take a concrete container and make =
a sequence out of it, they have to either check for emptiness or be in a pl=
ace where they can be assured that the container isn't empty. It is <i>very=
</i> easy to get it wrong, and if they do... boom. But not a loud boom.<br>=
<br>It's silent, but deadly.<br><br>Errors that are easy to do should be <i=
>noisy</i>, not silent.<br><br>Furthermore, you said:<br><br><blockquote st=
yle=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204)=
; padding-left: 1ex;" class=3D"gmail_quote">But the problem you are trying =
to solve is still of the mindset that a sequence is an iterator or range --=
when it's neither.<br></blockquote><div><br>Perhaps that is because you ha=
ve not provided a proper <i>conceptual</i> foundation for what you're propo=
sing. The C++ standard defines what an "iterator" is, conceptually. There's=
an informal understanding among C++ programmers what a "range" is.<br><br>=
If you're proposing some new conceptual idea that is distinct from other id=
eas, then you first need to <i>define</i> it. And you haven't. You've defin=
ed what the classes <i>do</i>, but not what they <i>mean</i> on a conceptua=
l level.<br><br>An InputIterator has some specific interface, but it also h=
as a conceptual meaning. It's an abstract, single-pass interface for extrac=
ting values from an ordered sequence of values (this is also another reason=
to avoid the "sequence" wording, because the standard already has things c=
alled "sequences"). We need some kind of conceptual foundation for these ob=
jects that helps explain and justify the design.<br><br>And when you're def=
ining these "sequences" conceptually, you should also answer questions like=
these:<br><br>Why is it <i>not</i> a range? Why have you defined it concep=
tually in such a way that it doesn't qualify as a range? What part of range=
s are you trying to "fix" with this concept? What part of the concept <i>re=
quires</i> it to not be empty? Is that an essential element of the concept?=
<br><br>And if it's true that "Sequences don't need to handle _every_ role =
regarding the possible ways one could approach this problem," why should we=
have them at all if there is a concept that <i>can</i> "handle every role"=
and allow us to solve problems more effectively?<br></div><br><br><br>On S=
aturday, June 15, 2013 5:21:58 PM UTC-7, carrieran...@yahoo.co.uk wrote:<bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;">On Saturday, June 15, 2013 3:26:3=
6 PM UTC-4, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>=
I'm in total agreement with Nevin on this: this is a complete deal-breaker.=
<br><br>What is the most common operation performed on an arbitrary range o=
f contiguously-allocated elements? Iteration=85<snip><br></div></bloc=
kquote><div><br></div><div>I've said it in multiple ways, including in the =
text you quoted: <b>A sequence is not an iterator.</b></div></blockquote><b=
r>You're right, sequences aren't iterators.<br><br>But I never said that th=
ey were, so your statement is a non-sequitur. I said that the most common o=
peration that someone would perform on a sequence would be <i>iteration</i>=
, but iteration does not require or even imply the use of an iterator. The =
most common operation people do on a `vector` or array is iteration too; th=
at doesn't make them iterators.<br><br><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div>So I don't regard it as good example. Real examples are =
better.</div><div><br></div><div>So an actual implementation might take the=
form:</div><div><br></div><div><div style=3D"background-color:rgb(250,250,=
250);border:1px solid rgb(187,187,187);word-wrap:break-word"><code><div><sp=
an style=3D"color:#008">void</span><span style=3D"color:#000"> func</span><=
span style=3D"color:#660">(</span><span style=3D"color:#000">std</span><spa=
n style=3D"color:#660">::</span><span style=3D"color:#000">sequence</span><=
span style=3D"color:#080"><int></span><span style=3D"color:#000"> sq<=
/span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span=
><span style=3D"color:#660">{</span><span style=3D"color:#000"><br> pr=
ocess</span><span style=3D"color:#660">(</span><span style=3D"color:#000">s=
q</span><span style=3D"color:#660">);</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">}</span></div></code></div><div><br></div=
></div><div>or</div><div><br></div><div><div style=3D"background-color:rgb(=
250,250,250);border:1px solid rgb(187,187,187);word-wrap:break-word"><code>=
<div><span style=3D"color:#008">void</span><span style=3D"color:#000"> func=
</span><span style=3D"color:#660">(</span><span style=3D"color:#000">std</s=
pan><span style=3D"color:#660">::</span><span style=3D"color:#000">sequence=
</span><span style=3D"color:#080"><int></span><span style=3D"color:#0=
00"> sq</span><span style=3D"color:#660">)</span><span style=3D"color:#000"=
> </span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#008">for</span><span style=3D"color:#000=
"> </span><span style=3D"color:#660">(</span><span style=3D"color:#008">aut=
o</span><span style=3D"color:#660">&</span><span style=3D"color:#000"> =
at</span><span style=3D"color:#660">:</span><span style=3D"color:#000">sq</=
span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>&nbs=
p; process</span><span style=3D"color:#660">(</span><span style=3D"color:#0=
00">at</span><span style=3D"color:#660">);</span><span style=3D"color:#000"=
><br></span><span style=3D"color:#660">}</span><span style=3D"color:#000"><=
br></span></div></code></div><br></div></blockquote><div><br>The problem wi=
th these "solutions" is that they don't actually solve the problem; not the=
problem that was outlined. The original example code very clearly stated t=
hat `process` took <i>two sequences</i>. The sole purpose of `func` was the=
refore to split a single sequence arbitrarily for consumption by `process`.=
<br><br>Since your examples don't actually do the same thing, they're inval=
id solutions to the problem at hand.<br><br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;"><blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>So why sho=
uld we go against <i>decades</i> of user experience here?<br></div></blockq=
uote><div><br></div><div>Let's not overstate -- References were introduced =
30 years ago.</div></blockquote><div><br>And yet, virtually every C++ objec=
t has value semantics. Imagine that; after 30 years, we're still using obje=
cts with value semantics.<br><br>Furthermore, my comment was in response to=
the lack of a valid empty state, not to your by-reference reference* seman=
tics. These are in fact separate issues; you can still have your by-referen=
ce reference semantics while defining the empty state as valid.<br><br>*: N=
ot a typo. "By-reference reference" means that the object functions like a =
C++ reference (thus "by-reference"), and the object conceptually acts as a =
reference to another object (the second "reference") that it does not own. =
This is to distinguish your "sequence" type from "by-value reference" types=
like `shared_ptr`. There, the object itself works by value (you can assign=
to it), but the object acts as a reference to another object that it does =
not (fully) own.<br><br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div>And speaking of decades of exp=
erience, that applies to the whole "immutable reference semantics" thing to=
o. Pretty much every object in the C++ standard library since C++98 uses <i=
>value</i> semantics. Even the istreams work by value-move; they just forbi=
d copying. They're mutable by default; if you want them to be immutable, yo=
u make them `const`. That's the <i>standard</i>.<br><br>The only objects th=
at don't use pure value semantics are those that explicitly reference thing=
s. And even those are by-<i>value</i> references: std::reference_wrapper ca=
n be re-seated, as can std::shared_ptr, and any other standard library refe=
rence-to-thing object.<br><br>So again, why should we go against how all ot=
her objects in the standard work? You've proven to yourself that such an im=
plementation <i>can</i> work and <i>can</i> be useful. That's great. But th=
at's not enough to say that it <i>should</i> be done, or that it should bec=
ome <i>standardized</i>.</div></blockquote><div> </div><div>And I ackn=
owledged that I expected resistance to the idea of reference-like semantics=
, and was offered to put out an implementation which supports both modes.&n=
bsp;We'll have to wait and see how it goes.</div></blockquote><div><br>My u=
ltimate point here is this: If you take those out, your proposal is no diff=
erent from `array_ref` besides the name. So why would yours succeed where a=
rray_ref failed?<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_1635_8944719.1371351324158--
.
Author: Chris Jefferson <chris@bubblescope.net>
Date: Sun, 16 Jun 2013 09:23:22 +0100
Raw View
This is a multi-part message in MIME format.
--------------040506090605060105000801
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
On 15/06/13 00:22, carrierandoperator@yahoo.co.uk wrote:
>
> 3. Why impose that size > 0 ?
>
>
> In my implementation, empty sequences are forbidden. That is by
> design. I've lived with this constraint in my implementation for years
> and have no desire or need to permit empty sequences in that
> implementation. I don't consider it a nuisance, but an aid. It
> increases memory safety, and provides narrow semantics similar to
> references.
>
Reasons to allow empty sequences.
1) The closest thing we have to sequences in C++ (pair of iterators),
already support empty sequences. The following compiles fine (sorry,
making up method names and abusing notation)
std::vector<int> v;
std::sort(v.begin(), v.end());
In a 'sequence' world, I assume the following would be undefined behaviour:
std::vector<int> v;
std::seq_sort(v);
I had a quick look for some code where empty ranges would be useful:
When ranges/sequences are more popular, I would really like to do things
like:
seq_print(seq_filter(v, function));
Would this be undefined if all elements of 'v' were rejected by
'function'. That would be unfortunate.
Chris
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--------------040506090605060105000801
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=windows-1252"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 15/06/13 00:22,
<a class="moz-txt-link-abbreviated" href="mailto:carrierandoperator@yahoo.co.uk">carrierandoperator@yahoo.co.uk</a> wrote:<br>
</div>
<blockquote
cite="mid:48e02950-675c-45af-a74b-2bb6a4831443@isocpp.org"
type="cite"><br>
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div>3. Why impose that size > 0 ?</div>
</blockquote>
<div><br>
</div>
<div>In my implementation, empty sequences are forbidden. That is
by design. I've lived with this constraint in my implementation
for years and have no desire or need to permit empty sequences
in that implementation. I don't consider it a nuisance, but an
aid. It increases memory safety, and provides narrow semantics
similar to references.</div>
<div><br>
</div>
</blockquote>
<br>
Reasons to allow empty sequences.<br>
<br>
1) The closest thing we have to sequences in C++ (pair of
iterators), already support empty sequences. The following compiles
fine (sorry, making up method names and abusing notation)<br>
<br>
std::vector<int> v;<br>
std::sort(v.begin(), v.end()); <br>
<br>
In a 'sequence' world, I assume the following would be undefined
behaviour:<br>
<br>
std::vector<int> v;<br>
std::seq_sort(v);<br>
<br>
I had a quick look for some code where empty ranges would be useful:<br>
<br>
When ranges/sequences are more popular, I would really like to do
things like:<br>
<br>
seq_print(seq_filter(v, function));<br>
<br>
Would this be undefined if all elements of 'v' were rejected by
'function'. That would be unfortunate.<br>
<br>
Chris<br>
<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
<br />
<br />
--------------040506090605060105000801--
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Sun, 16 Jun 2013 05:45:04 -0400
Raw View
--Apple-Mail=_C3F2FF8A-1F52-477B-BB44-8BC8F48A82C6
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=windows-1252
On Jun 15, 2013, at 10:55 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> OK, this is clearly coming down to a "religious" issue. You have come to =
the belief that an empty "sequence" represents an invalid state comparable =
to a NULL pointer. You therefore believe that any operation that generates =
an empty sequence represents an erroneous operation. And therefore you beli=
eve that your system should explicitly disallow this possibility.
I do favor semantics like references, but am investing a good chunk of time=
drafting an implementation which supports one or the other. I've also stat=
ed that it would be fine by me to remove that restriction if there is enoug=
h opposition. Ideally, that opposition would also be justified by actual pr=
oblems (demonstrated using a draft implementation). That shouldn't prevent =
me from defending or justifying those semantics when/if somebody objects to=
them within a dialogue. So I state my position, you disagree, I then elabo=
rate in defense of my design choice in response; How is that a bad thing? T=
his is how designs are improved and understanding is attained.
> The entire rest of the world disagrees with you.
echo "Let's not overstate"
> Virtually every API that takes a sequence of contiguously allocated objec=
ts will accept an empty sequence thereof, regardless of how that API might =
define an empty sequence.
This is also an overstatement. I explained why this is often an error, as w=
ell as reminded you that you would still have all the mechanisms you have t=
oday to express the intention where an input may be effectively null or emp=
ty. Where an author specifies a parameter is a sequence and a sequence is f=
orbidden from being empty that states a contract very clearly.
> Be that as it may, if you wish to persist with this notion that "empty =
=3D=3D invalid =3D=3D error", then you need to be serious about it. And tha=
t means you need to throw an exception on any circumstance that would resul=
t in an empty range. Merely being "undefined behavior" isn't enough, even b=
y your own standard:
>=20
> It localizes that logic and error to precisely where it needs to be, forb=
idding the error from propagating (or continuing in a defined manner).
>=20
> Even if we assume that generating an empty range is a logic error, you ca=
n't forbid a logic error if you allow the program to continue. Calling it "=
undefined" is objectively worse than either throwing or allowing sequences =
to be empty.
These are very easy (local) logic errors. Nevertheless, you are writing as =
though I strongly oppose throwing in this scenario. I'll quote myself:
Alex B: =85will result in undefined behavior if the vector is empty?
Me: Either that or throw an exception. Whichever response would be least su=
rprising.
Exceptions were touched on. I feel my stance was one which does not need st=
rong opposition (you can't distance yourself far from me if I am near the m=
iddle). I also calmly reintroduced throwing as a possibility where you disr=
egarded those words in your previous post (when you said "The way you want =
it=85"). Why distort my words to build an argument that is based on fallacy=
?
> If sequences could be empty, then algorithms that could break on empty se=
quences could be written defensively and thus check for them and return app=
ropriate values (see every C/C++ function that takes a range).
I'm calling out your overstatement again. Do you notice a trend where I cal=
l out your overstatements and then quietly disregard the point you are tryi=
ng to make? Sure, there are valid underlying points you have to make and so=
metimes I want to agree, comment, or correct you -- but I am not going to b=
other in some cases because you blow a lot of things out of proportion such=
that they are not factual and/or ultimately not persuasive. Sure, I could =
demonstrate that your overblown statements are false, but that's just going=
to kill my time/patience and allow you to derail the conversation. Let's k=
eep it factual and on topic. Thanks :)
> And if operations that produce empty sequences throw, then it is very eas=
y to track down exactly who's responsible for the empty sequence, since it =
would throw an exception at the moment of creation.
>=20
> By making it undefined, you get the worst of both worlds: you can't write=
defensively against undefined behavior, and you can't guarantee you get th=
e actual program break in the place where the brokenness originated.
>=20
> Now, let me head off the incoming "perfidy" argument, that C++ doesn't pr=
otect users from willful misuse, only accidental misuse. For example, there=
's nothing in C++ that allows you to defend a function from a "null referen=
ce" either.
>=20
> However, there's a big difference between a null reference and this: name=
ly in how hard it is to screw it up.
>=20
> It's actually rather difficult to create a null reference by accident in =
C++; you pretty much have to be trying to do it. To generate one that, you =
must at some point in your code take a pointer (which you haven't checked a=
gainst NULL) and do this with it: `T &t =3D *ptr;`.
>=20
> That's always suspect code. And it's generally pretty easy to track down =
where and when that could happen, especially if direct, naked pointer use i=
n your program is rare.
Thanks for voicing your preference and defending it.
The draft implementation has two error modes; One where it aborts, and anot=
her where it throws. Note: This doesn't mean that abort would replace UB if=
people think exceptions should be avoided. There are some cases where chec=
ks are absent (e.g. op[] is the predictable one).
When exceptions are the enabled error mechanism:
- std::logic_error is thrown from the constructor if the sequence is empty=
and empty sequences are forbidden.
- std::invalid_argument is thrown if the pointer is null and empty sequenc=
es are forbidden.
- std::invalid_argument is thrown if the size is 0 and empty sequences are=
forbidden.
- std::invalid_argument is thrown if the pointer is null and n is non-zero=
..
- std::logic_error may be thrown if the size is 0 and empty sequences are =
forbidden
- std::length_error may be thrown if the size exceeds max_size()
- std::out_of_range on at()
- std::range_error may be thrown when slicing
- std::out_of_range may be thrown on front() or back() if the sequence is =
empty and empty sequences are permitted
But I haven't gone as far as determined whether or not that list is complet=
e at this time. Also, copying sequence->sequence is not checked (a failure =
at that point should be unreachable).
> By contrast, an empty sequence is very easy to create. It's as simple as =
this:
>=20
> void func(sequence<int> seq);
>=20
> vector<int> v;
> //Lots of arbitrary code that does *not* fill in `v`.
> func(v);
>=20
> This looks like perfectly legitimate code. If someone were doing a code r=
eview of it, it would seem on the surface to be reasonable. It's only not r=
easonable because of the limitations of sequence. Which, as previously esta=
blished, go against every expectation of most C/C++ APIs. Which also means =
that it goes against the expectations of most C/C++ programmers. So most pr=
ogrammers will look at this code and expect it to work.
The author's intent conveyed to the caller is: "func() must be passed a min=
imum of one element". But this is not really a revolutionary concept, certa=
inly not within the domain of reference semantics. Consider any API that fo=
rbids one from passing a Null pointer or dereferencing. The analogous count=
erexample would be:
const char* v(nullptr);
// Lots of arbitrary code that does *not* assign `v`.
return std::strlen(v);
> The way you want to do things, every time the user wants to take a concre=
te container and make a sequence out of it, they have to either check for e=
mptiness or be in a place where they can be assured that the container isn'=
t empty. It is very easy to get it wrong, and if they do...
And this goes back to pushing the logic out of preconditions of all (defens=
ive) definitions to the points where such logic errors may be introduced. O=
nce you have constructed a valid sequence, you can just push it through man=
y functions or copy it as needed -- without those functions needing to vali=
date parameters. But you do need to think for a moment when you "bind that =
reference" from a vector's elements or slice/divide a sequence. By the way,=
known sizes (e.g. std::array<> and static sized C arrays) do not require r=
untime checks. So the constructors that this applies to are:
- std::vector<>
- and the primitive ctors: ptr+size and ptr+ptr (and the latter may get th=
e axe).
> boom. But not a loud boom.
Again, I have reigned exceptions into the conversation multiple times. Don'=
t word it as though I have excluded them. Also, if "undefined", would a lib=
rary implementation not have the liberty to abort or otherwise boom loudly?=
Would the developer not have the option to enable debug mode?
> It's silent, but deadly.
>=20
> Errors that are easy to do should be noisy, not silent.
>=20
> Furthermore, you said:
>=20
> But the problem you are trying to solve is still of the mindset that a se=
quence is an iterator or range -- when it's neither.
>=20
> Perhaps that is because you have not provided a proper conceptual foundat=
ion for what you're proposing. The C++ standard defines what an "iterator" =
is, conceptually. There's an informal understanding among C++ programmers w=
hat a "range" is.
>=20
> If you're proposing some new conceptual idea that is distinct from other =
ideas, then you first need to define it. And you haven't. You've defined wh=
at the classes do, but not what they mean on a conceptual level.
Fair enough. The intent and uses were presented in the draft above, but evi=
dently not clearly enough. I don't have the fresh perspective, so these dis=
cussions help clarify what's not obvious to somebody with a fresh perspecti=
ve.
> An InputIterator has some specific interface, but it also has a conceptua=
l meaning. It's an abstract, single-pass interface for extracting values fr=
om an ordered sequence of values (this is also another reason to avoid the =
"sequence" wording, because the standard already has things called "sequenc=
es"). We need some kind of conceptual foundation for these objects that hel=
ps explain and justify the design.
>=20
> And when you're defining these "sequences" conceptually, you should also =
answer questions like these:
Noted -- I'll address these directly in the next draft revision.
I'll assume these are mostly rhetorical and supporting the larger point you=
are making, but I'll briefly respond for anyone who is dropping in at this=
point.
> Why is it not a range?
> Why have you defined it conceptually in such a way that it doesn't qualif=
y as a range?
> And if it's true that "Sequences don't need to handle _every_ role regard=
ing the possible ways one could approach this problem," why should we have =
them at all if there is a concept that can "handle every role" and allow us=
to solve problems more effectively?
Because it needn't be a range. A sequence represents an array of one or mor=
e elements whose lifetime/location is external. Although ranges can express=
a similar construct, ranges solve a different problem. I have used (and ev=
en written) range implementations. They are incredibly complex in relation =
what sequences aim to achieve. They are separate tools for separate purpose=
s. To consider a range as a substitute because it _could_ solve the same pr=
oblem is to use a range as a Golden Hammer (based on many range implementat=
ions I have seen).
I'm also left to believe std::range is still far from complete/standardizat=
ion; Olaf mentioned std::range above, but by not responding to my question =
about its status I am left to believe it's still vaporware or liable to cha=
nge significantly. Why hold my breath, especially when it is likely a far m=
ore complex representation of the problems sequences aim squarely at? My su=
spicion is that they are an unnecessarily "rich" way to represent a sequenc=
e, and that may not be a good thing for a few reasons.
> What part of ranges are you trying to "fix" with this concept?
> What part of the concept requires it to not be empty? Is that an essentia=
l element of the concept?
A sequence is focused on a distinct and clearly defined objective. It's not=
an attempt to "fix" or replace ranges. Furthermore, there are very valid r=
easons why an implementation may specify that it must be passed contiguous =
elements _only_.
Reference semantics were chosen because it is a clear path to introduce gua=
rantees which strengthen programs' correctness and can ultimately reduce pr=
ogram complexity greatly if used in the right places and for the right reas=
ons. I've used reference semantics in my implementation for years (since it=
was initially written), and it's a feature I have no desire to remove (fro=
m that implementation). As mentioned, I expect opposition to this and can b=
e convinced that the majority does not favor reference-like semantics. The =
proposed implementation isn't for my needs; it's for everybody's use. Objec=
t references have been around for 30 years in C++, but arrays are an odd ov=
ersight. Why should we jump back to the 1980s or impose storage restriction=
s (seen in the draft's examples) when dealing with an array?
The other problem reference semantics achieve is good locality. We have ref=
erences and smart pointers for objects as well as safe, checked containers =
which can greatly reduce problems such as dangling pointers, manage object =
lifetimes, abstract ownership, and abstract underlying storage. If sequence=
s were natured like pointers (e.g. assignable or null), their scope could b=
e easily expanded (easier to have dangling pointers and cause an explosion =
of validation logic downstream); _then_ the type would be a marginal improv=
ement over pointer and size (but still beneficial). Object references solve=
many problems and simplify programs if used in the right places. Notation =
isn't the only reason to use them, the semantics they introduce are very im=
portant. But 30 years later, we have no (common) equivalent for arrays. Lik=
e people still use pointers in C++ after 30 years, there is nothing which p=
rohibits you from using pointer+size to represent contiguous elements (or m=
aybe iterator, range, pair, or direct container manipulation is more sensib=
le for whatever problem you face that day). So, why not strive to provide r=
eference-like semantics for arrays? If reference semantics are considered f=
avorable, then it would seem essential that empty is forbidden. No? Referen=
ce semantics are a topic "Open for Discussion", but I think reference seman=
tics are worth strong consideration because (*I* believe) that's going to d=
o more to improve programs than sticking to pointer semantics. It's going t=
o offer a more diverse toolset.
When reference semantics are to be applied to an *object* we have a good me=
chanism to represent that. We also have a good means to express pointer sem=
antics for an object. We have good ways to pass an array using pointer sema=
ntics. We do NOT have a good way to represent an array with reference seman=
tics. We're either left exposing storage/container, using generics, or allo=
wing ambiguities inherent to pointer semantics to propagate (far from the o=
rigin of error).
Tony Hoare - Speaking at a conference in 2009, Hoare apologized for inventi=
ng the null reference: "I call it my billion-dollar mistake. It was the inv=
ention of the null reference=85"
Meanwhile, languages such as Rust aim to prohibit dangling pointers.
> On Saturday, June 15, 2013 5:21:58 PM UTC-7, carrieran...@yahoo.co.uk wro=
te:
> On Saturday, June 15, 2013 3:26:36 PM UTC-4, Nicol Bolas wrote:
> I'm in total agreement with Nevin on this: this is a complete deal-breake=
r.
>=20
> What is the most common operation performed on an arbitrary range of cont=
iguously-allocated elements? Iteration=85<snip>
>=20
> I've said it in multiple ways, including in the text you quoted: A sequen=
ce is not an iterator.
>=20
> You're right, sequences aren't iterators.
>=20
> But I never said that they were, so your statement is a non-sequitur. I s=
aid that the most common operation that someone would perform on a sequence=
would be iteration, but iteration does not require or even imply the use o=
f an iterator. The most common operation people do on a `vector` or array i=
s iteration too; that doesn't make them iterators.
>=20
> So I don't regard it as good example. Real examples are better.
>=20
> So an actual implementation might take the form:
>=20
> void func(std::sequence<int> sq) {
> process(sq);
> }
>=20
> or
>=20
> void func(std::sequence<int> sq) {
> for (auto& at:sq)
> process(at);
> }
>=20
>=20
> The problem with these "solutions" is that they don't actually solve the =
problem; not the problem that was outlined. The original example code very =
clearly stated that `process` took two sequences. The sole purpose of `func=
` was therefore to split a single sequence arbitrarily for consumption by `=
process`.
>=20
> Since your examples don't actually do the same thing, they're invalid sol=
utions to the problem at hand.
I did note when I deviated, and I did agree that in some cases it does requ=
ire additional logic. I then explained how that additional logic generally =
tends to simplify programs as a whole because it allows you to remove logic=
from other parts of your program -- who tests the address of a parameter p=
assed by reference? Just move the logic to where it needs to be and it tend=
s to simplify the program. I then reaffirmed that sequences are not designe=
d to replace other types, like increasing the vocabulary of a language.
>=20
> So why should we go against decades of user experience here?
>=20
> Let's not overstate -- References were introduced 30 years ago.
>=20
> And yet, virtually every C++ object has value semantics. Imagine that; af=
ter 30 years, we're still using objects with value semantics.
>=20
> Furthermore, my comment was in response to the lack of a valid empty stat=
e, not to your by-reference reference* semantics. These are in fact separat=
e issues; you can still have your by-reference reference semantics while de=
fining the empty state as valid.
So what do you think is ideal for this type? Based on our exchanges, I am l=
ed to believe you favor "pointer semantics" -- where (re)assignment and nul=
l are qualities worth debating in favor of.
> *: Not a typo. "By-reference reference" means that the object functions l=
ike a C++ reference (thus "by-reference"), and the object conceptually acts=
as a reference to another object (the second "reference") that it does not=
own. This is to distinguish your "sequence" type from "by-value reference"=
types like `shared_ptr`. There, the object itself works by value (you can =
assign to it), but the object acts as a reference to another object that it=
does not (fully) own.
>=20
> And speaking of decades of experience, that applies to the whole "immutab=
le reference semantics" thing too. Pretty much every object in the C++ stan=
dard library since C++98 uses value semantics. Even the istreams work by va=
lue-move; they just forbid copying. They're mutable by default; if you want=
them to be immutable, you make them `const`. That's the standard.
>=20
> The only objects that don't use pure value semantics are those that expli=
citly reference things. And even those are by-value references: std::refere=
nce_wrapper can be re-seated, as can std::shared_ptr, and any other standar=
d library reference-to-thing object.
>=20
> So again, why should we go against how all other objects in the standard =
work? You've proven to yourself that such an implementation can work and ca=
n be useful. That's great. But that's not enough to say that it should be d=
one, or that it should become standardized.
> =20
> And I acknowledged that I expected resistance to the idea of reference-li=
ke semantics, and was offered to put out an implementation which supports b=
oth modes. We'll have to wait and see how it goes.
>=20
> My ultimate point here is this: If you take those out, your proposal is n=
o different from `array_ref` besides the name. So why would yours succeed w=
here array_ref failed?
A big point is that array_ref does not represent mutable elements. Sequence=
s *do* represent mutable elements. That's a huge difference, IMO. The imple=
mentation I am working also has some things which increase type safety. You=
asked me this at the previous revision and I answered you in detail -- abo=
ut 1.5 pages. I also mentioned sequence_n<>, octet_sequence, etc. in this r=
ev.
As to why they might accept this after rejecting array_ref: Reference-like =
semantics are still an option, and there are still several differences. If =
llvm found a need for mutable array refs just last year=85 well, I may have=
more code that relies on this type than theirs. It could be different enou=
gh from array_ref and perhaps more refined than array_ref that it may be wo=
rth consideration. I also see disappointment that array_ref did not pass. I=
'm actually quite curious as to what the reason for rejection was. Finally,=
array_ref has been dormant for a while... and how far away are ranges?
Thanks
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_C3F2FF8A-1F52-477B-BB44-8BC8F48A82C6
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=windows-1252
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Jun =
15, 2013, at 10:55 PM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.co=
m">jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-interchange-n=
ewline"><blockquote type=3D"cite">OK, this is clearly coming down to a "rel=
igious" issue. You have come to
the belief that an empty "sequence" represents an invalid state=20
comparable to a NULL pointer. You therefore believe that any operation that=
generates an empty sequence represents an erroneous operation. And therefo=
re you believe that your system
should explicitly disallow this possibility.<br></blockquote><span style=
=3D"font-family: helvetica; font-size: 13px; background-color: rgb(255, 255=
, 255); "><div><span style=3D"font-family: helvetica; font-size: 13px; back=
ground-color: rgb(255, 255, 255); "><br></span></div>I do favor semantics l=
ike references, but am investing a good chunk of time drafting an implement=
ation which supports one or the other. I've also stated that it would be fi=
ne by me to remove that restriction if there is enough opposition. Ideally,=
that opposition would also be justified by actual problems (demonstrated u=
sing a draft implementation). That shouldn't prevent me from defending or j=
ustifying those semantics when/if somebody objects to them within a dialogu=
e. So I state my position, you disagree, I then elaborate in defense of my =
design choice in response; How is that a bad thing? This is how designs are=
improved and understanding is attained.</span></div><div><font face=3D"hel=
vetica"><span style=3D"font-size: 13px;"><br></span></font><blockquote type=
=3D"cite">The entire rest of the world disagrees with=20
you.</blockquote><div><br></div><div>echo "Let's not overstate"</div><div><=
br></div><br><blockquote type=3D"cite">Virtually every API that takes a seq=
uence of contiguously allocated objects will accept an empty sequence there=
of, regardless of how that API might define an empty sequence.<br></blockqu=
ote><div><br></div><div>This is also an overstatement. I explained why this=
is often an error, as well as reminded you that you would still have all t=
he mechanisms you have today to express the intention where an input may be=
effectively null or empty. Where an author specifies a parameter is a sequ=
ence and a sequence is forbidden from being empty that states a contract ve=
ry clearly.</div><br><blockquote type=3D"cite">Be that as it may, if you wi=
sh to persist with this notion that "empty =3D=3D invalid =3D=3D error", th=
en you need to be <i>serious</i> about it. And that means you <i>need</i> t=
o throw an exception on any circumstance that would result in an empty rang=
e. Merely being "undefined behavior" isn't enough, even by your own standar=
d:<br><br><blockquote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px =
solid rgb(204, 204, 204); padding-left: 1ex;" class=3D"gmail_quote">It loca=
lizes that logic and error to precisely where it needs to be, forbidding th=
e error from propagating (or continuing in a defined manner).<br></blockquo=
te><br>Even if we assume that generating an empty range is a logic error, y=
ou can't <i>forbid</i> a logic error if you allow the program to continue. =
Calling it "undefined" is objectively <i>worse</i> than either throwing or =
allowing sequences to be empty.<br></blockquote><div><br></div><div>These a=
re very easy (local) logic errors. Nevertheless, you are writing as though =
I strongly oppose throwing in this scenario. I'll quote myself:</div><div><=
br></div><div><span style=3D"color: rgb(80, 0, 80); font-family: Arial, Hel=
vetica, sans-serif; font-size: 13px; background-color: rgb(255, 255, 255); =
">Alex B: =85will result in undefined behavior if the vector is empty?</spa=
n></div><div>Me: <span style=3D"background-color: rgb(255, 255, 255); color=
: rgb(34, 34, 34); font-family: Arial, Helvetica, sans-serif; font-size: 13=
px; ">Either that or throw an exception. Whichever response would be least =
surprising.</span></div><div><span style=3D"background-color: rgb(255, 255,=
255); color: rgb(34, 34, 34); font-family: Arial, Helvetica, sans-serif; f=
ont-size: 13px; "><br></span></div><div><span style=3D"background-color: rg=
b(255, 255, 255); color: rgb(34, 34, 34); font-family: Arial, Helvetica, sa=
ns-serif; font-size: 13px; ">Exceptions were touched on. I feel my stance w=
as one which does not need strong opposition (you can't distance yourself f=
ar from me if I am near the middle). I also calmly reintroduced throwing as=
a possibility where you disregarded those words in your previous post (whe=
n you said "The way you want it=85"). Why distort my words to build an argu=
ment that is based on fallacy?</span></div><div><span style=3D"background-c=
olor: rgb(255, 255, 255); color: rgb(34, 34, 34); font-family: Arial, Helve=
tica, sans-serif; font-size: 13px; "><br></span></div><br><blockquote type=
=3D"cite">If sequences could be empty, then algorithms that could break on =
empty sequences could be written <i>defensively</i> and thus check for them=
and return appropriate values (see every C/C++ function that takes a range=
).</blockquote><div><br></div><div>I'm calling out your overstatement <i>ag=
ain</i>. Do you notice a trend where I call out your overstatements and the=
n quietly disregard the point you are trying to make? Sure, there are valid=
underlying points you have to make and sometimes I want to agree, comment,=
or correct you -- but I am not going to bother in some cases because you b=
low a lot of things out of proportion such that they are not factual and/or=
ultimately not persuasive. Sure, I could demonstrate that your overblown s=
tatements are false, but that's just going to kill my time/patience and all=
ow you to derail the conversation. Let's keep it factual and on topic. Than=
ks :)</div><br><blockquote type=3D"cite">And if operations that produce emp=
ty sequences throw, then it is very easy to track down exactly who's respon=
sible for the empty sequence, since it would throw an exception at the mome=
nt of creation.<br><br>By making it undefined, you get the <i>worst</i> of =
both worlds: you can't write defensively against undefined behavior, and yo=
u can't guarantee you get the actual program break in the place where the b=
rokenness <i>originated</i>.<br><br>Now, let me head off the incoming "perf=
idy" argument, that C++ doesn't protect users from <i>willful</i> misuse, o=
nly accidental misuse. For example, there's nothing in C++ that allows you =
to defend a function from a "null reference" either.<br><br>However, there'=
s a big difference between a null reference and this: namely in how hard it=
is to screw it up.<br><br>It's actually rather difficult to create a null =
reference <i>by accident</i> in C++; you pretty much have to be <i>trying</=
i> to do it. To generate one that, you must at some point in your code take=
a pointer (which you haven't checked against NULL) and do this with it: `T=
&t =3D *ptr;`.<br><br>That's always suspect code. And it's generally p=
retty easy to track down where and when that could happen, especially if di=
rect, naked pointer use in your program is rare.<br></blockquote><div><br><=
/div><div>Thanks for voicing your preference and defending it.</div><div><b=
r></div><div>The draft implementation has two error modes; One where it abo=
rts, and another where it throws. Note: This doesn't mean that abort would =
replace UB if people think exceptions should be avoided. There are some cas=
es where checks are absent (e.g. op[] is the predictable one).</div><div><b=
r></div><div>When exceptions are the enabled error mechanism:</div><div><sp=
an class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>- std::logic_=
error is thrown from the constructor if the sequence is empty and empty seq=
uences are forbidden.</div><div><span class=3D"Apple-tab-span" style=3D"whi=
te-space: pre; "> </span>- std::invalid_argument is thrown if the pointer i=
s null and empty sequences are forbidden.</div><div><span class=3D"Apple-ta=
b-span" style=3D"white-space:pre"> </span>- std::invalid_argument is thrown=
if the size is 0 and empty sequences are forbidden.</div><div><span class=
=3D"Apple-tab-span" style=3D"white-space: pre; "> </span>- std::invalid_arg=
ument is thrown if the pointer is null and <i>n</i> is non-zero.</div>=
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>- std=
::logic_error may be thrown if the size is 0 and empty sequences are forbid=
den</div><div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </s=
pan>- std::length_error may be thrown if the size exceeds max_size()</div><=
div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>- std:=
:out_of_range on at()</div><div><span class=3D"Apple-tab-span" style=3D"whi=
te-space:pre"> </span>- std::range_error may be thrown when slicing</div><d=
iv><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>- std::=
out_of_range may be thrown on front() or back() if the sequence is empty an=
d empty sequences are permitted</div><div><br></div><div>But I haven't gone=
as far as determined whether or not that list is complete at this time. Al=
so, copying sequence->sequence is not checked (a failure at th=
at point should be unreachable).</div><div><br></div><div><br></div><br><bl=
ockquote type=3D"cite">By contrast, an empty sequence is <i>very</i> easy t=
o create. It's as simple as this:<br><br><div class=3D"prettyprint" style=
=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 1=
87); word-wrap: break-word; position: static; z-index: auto; "><code class=
=3D"prettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">=
void</span> func<span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span>sequence<span style=3D"color: #080;" class=3D"styled-by-prettify">&l=
t;int></span> seq<span style=3D"color: #660;" class=3D"styled-by-prettif=
y">);</span><br><br>vector<span style=3D"color: #080;" class=3D"styled-by-p=
rettify"><int></span> v<span style=3D"color: #660;" class=3D"styled-b=
y-prettify">;</span><br><span style=3D"color: #800;" class=3D"styled-by-pre=
ttify">//Lots of arbitrary code that does *not* fill in `v`.</span><br>func=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(</span>v<span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">);</span></code></div><br=
>This <i>looks</i> like perfectly legitimate code. If someone were doing a =
code review of it, it would seem on the surface to be reasonable. It's only=
not reasonable because of the limitations of sequence. Which, as previousl=
y established, go against every expectation of most C/C++ APIs. Which also =
means that it goes against the expectations of most C/C++ <i>programmers</i=
>. So most programmers will look at this code and expect it to work.<br></b=
lockquote><div><br></div><div>The author's intent conveyed to the caller is=
: "func() must be passed a minimum of one element". But this is not really =
a revolutionary concept, certainly not within the domain of reference seman=
tics. Consider any API that forbids one from passing a Null pointer or dere=
ferencing. The analogous counterexample would be:</div><div><br></div><div>=
<div> const char* v(nullptr);</div><div> // Lots of arbitrary c=
ode that does *not* assign `v`.</div><div> return std::strlen(v);</di=
v><div><br></div></div><br><blockquote type=3D"cite">The way you want to do=
things, <i>every time</i> the user wants to take a concrete container and =
make a sequence out of it, they have to either check for emptiness or be in=
a place where they can be assured that the container isn't empty. It is <i=
>very</i> easy to get it wrong, and if they do...</blockquote><div><br></di=
v><div>And this goes back to pushing the logic out of preconditions of all =
(defensive) definitions to the points where such logic errors may be introd=
uced. Once you have constructed a valid sequence, you can just push it thro=
ugh many functions or copy it as needed -- without those functions needing =
to validate parameters. But you do need to think for a moment when you "bin=
d that reference" from a vector's elements or slice/divide a sequence. By t=
he way, known sizes (e.g. std::array<> and static sized C arrays) do =
not require runtime checks. So the constructors that this applies to are:</=
div><div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>-=
std::vector<></div><div><span class=3D"Apple-tab-span" style=3D=
"white-space:pre"> </span>- and the primitive ctors: ptr+size and ptr+=
ptr (and the latter may get the axe).</div><br><blockquote type=3D"cite">bo=
om. But not a loud boom.<br></blockquote><div><br></div><div>Again, I have =
reigned exceptions into the conversation multiple times. Don't word it as t=
hough I have excluded them. Also, if "undefined", would a library implement=
ation not have the liberty to abort or otherwise boom loudly? Would the dev=
eloper not have the option to enable debug mode?</div><br><blockquote type=
=3D"cite">It's silent, but deadly.<br><br>Errors that are easy to do should=
be <i>noisy</i>, not silent.<br><br>Furthermore, you said:<br><br><blockqu=
ote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204=
, 204); padding-left: 1ex;" class=3D"gmail_quote">But the problem you are t=
rying to solve is still of the mindset that a sequence is an iterator or ra=
nge -- when it's neither.<br></blockquote><div><br>Perhaps that is because =
you have not provided a proper <i>conceptual</i> foundation for what you're=
proposing. The C++ standard defines what an "iterator" is, conceptually. T=
here's an informal understanding among C++ programmers what a "range" is.<b=
r><br>If you're proposing some new conceptual idea that is distinct from ot=
her ideas, then you first need to <i>define</i> it. And you haven't. You've=
defined what the classes <i>do</i>, but not what they <i>mean</i> on a con=
ceptual level.<br></div></blockquote><div><br></div><div>Fair enough. The i=
ntent and uses were presented in the draft above, but evidently not clearly=
enough. I don't have the fresh perspective, so these discussions help clar=
ify what's not obvious to somebody with a fresh perspective.</div><br><bloc=
kquote type=3D"cite"><div>An InputIterator has some specific interface, but=
it also has a conceptual meaning. It's an abstract, single-pass interface =
for extracting values from an ordered sequence of values (this is also anot=
her reason to avoid the "sequence" wording, because the standard already ha=
s things called "sequences"). We need some kind of conceptual foundation fo=
r these objects that helps explain and justify the design.<br><br>And when =
you're defining these "sequences" conceptually, you should also answer ques=
tions like these:<br></div></blockquote><div><br></div><div>Noted -- I'll a=
ddress these directly in the next draft revision.</div><div><br></div><div>=
I'll assume these are mostly rhetorical and supporting the larger point you=
are making, but I'll briefly respond for anyone who is dropping in at this=
point.</div><br><blockquote type=3D"cite"><div>Why is it <i>not</i> a rang=
e?</div></blockquote><div><div><blockquote type=3D"cite">Why have you defin=
ed it conceptually in such a way that it doesn't qualify as a range?</block=
quote><div><div><blockquote type=3D"cite">And if it's true that "Sequences =
don't need to handle _every_ role regarding the possible ways one could app=
roach this problem," why should we have them at all if there is a concept t=
hat <i>can</i> "handle every role" and allow us to solve problems=
more effectively?<br></blockquote><div><br></div></div></div></div></div><=
div>Because it needn't be a range. A sequence represents an array of one or=
more elements whose lifetime/location is external. Although ranges can exp=
ress a similar construct, ranges solve a different problem. I have used (an=
d even written) range implementations. They are incredibly complex in relat=
ion what sequences aim to achieve. They are separate tools for separate pur=
poses. To consider a range as a substitute because it _could_ solve the sam=
e problem is to use a range as a Golden Hammer (based on many range impleme=
ntations I have seen).</div><div><br></div><div>I'm also left to believe st=
d::range is still far from complete/standardization; Olaf mentioned std::ra=
nge above, but by not responding to my question about its status I am left =
to believe it's still vaporware or liable to change significantly. Why hold=
my breath, especially when it is likely a far more complex representation =
of the problems sequences aim squarely at? My suspicion is that they are an=
unnecessarily "rich" way to represent a sequence, and that may not be a go=
od thing for a few reasons.</div><div><br></div><blockquote type=3D"cite"><=
div>What part of ranges are you trying to "fix" with this concept?</div></b=
lockquote><div><blockquote type=3D"cite">What part of the concept <i>r=
equires</i> it to not be empty? Is that an essential element of t=
he concept?</blockquote><div><br></div></div><div>A sequence is focused on =
a distinct and clearly defined objective. It's not an attempt to "fix" or r=
eplace ranges. Furthermore, there are very valid reasons why an implementat=
ion may specify that it must be passed contiguous elements _only_.</div><di=
v><br></div><div>Reference semantics were chosen because it is a clear path=
to introduce guarantees which strengthen programs' correctness and can ult=
imately reduce program complexity greatly if used in the right places and f=
or the right reasons. I've used reference semantics in my implementation fo=
r years (since it was initially written), and it's a feature I have no desi=
re to remove (from that implementation). As mentioned, I expect opposition =
to this and can be convinced that the majority does not favor reference-lik=
e semantics. The proposed implementation isn't for my needs; it's for every=
body's use. Object references have been around for 30 years in C++, but arr=
ays are an odd oversight. Why should we jump back to the 1980s or impose st=
orage restrictions (seen in the draft's examples) when dealing with an arra=
y?</div><div><br></div><div>The other problem reference semantics achieve i=
s good locality. We have references and smart pointers for objects as well =
as safe, checked containers which can greatly reduce problems such as dangl=
ing pointers, manage object lifetimes, abstract ownership, and abstract und=
erlying storage. If sequences were natured like pointers (e.g. assignable o=
r null), their scope could be easily expanded (easier to have dangling poin=
ters and cause an explosion of validation logic downstream); _then_ the typ=
e would be a marginal improvement over pointer and size (but still benefici=
al). Object references solve many problems and simplify programs if used in=
the right places. Notation isn't the only reason to use them, the semantic=
s they introduce are very important. But 30 years later, we have no (common=
) equivalent for arrays. Like people still use pointers in C++ after 30 yea=
rs, there is nothing which prohibits you from using pointer+size to represe=
nt contiguous elements (or maybe iterator, range, pair, or direct container=
manipulation is more sensible for whatever problem you face that day). So,=
why not strive to provide reference-like semantics for arrays? If referenc=
e semantics are considered favorable, then it would seem essential that emp=
ty is forbidden. No? Reference semantics are a topic "Open for Discussion",=
but I think reference semantics are worth strong consideration because (*I=
* believe) that's going to do more to improve programs than sticking to poi=
nter semantics. It's going to offer a more diverse toolset.</div><div><br><=
/div><div>When reference semantics are to be applied to an *object* we have=
a good mechanism to represent that. We also have a good means to express p=
ointer semantics for an object. We have good ways to pass an array using po=
inter semantics. We do NOT have a good way to represent an array with refer=
ence semantics. We're either left exposing storage/container, using generic=
s, or allowing ambiguities inherent to pointer semantics to propagate (far =
from the origin of error).</div><div><br></div><div><a href=3D"http://en.wi=
kipedia.org/wiki/Tony_Hoare#Quotations">Tony Hoare - <span style=3D"ba=
ckground-color: rgb(255, 255, 255); font-family: sans-serif; font-size: 13p=
x; line-height: 19px; ">Speaking at a conference in 2009, Hoare apologized =
for inventing the</span><span style=3D"background-color: rgb(255, 255, 255)=
; font-family: sans-serif; font-size: 13px; line-height: 19px; "> </sp=
an><font color=3D"#0b0080" face=3D"sans-serif"><span style=3D"font-size: 13=
px; line-height: 19px;">null reference</span></font><span style=3D"backgrou=
nd-color: rgb(255, 255, 255); font-family: sans-serif; font-size: 13px; lin=
e-height: 19px; ">: </span><span style=3D"background-color: rgb(255, 2=
55, 255); font-family: sans-serif; font-size: 13px; line-height: 19px; ">"I=
call it my billion-dollar mistake. It was the invention of the null refere=
nce</span><span style=3D"background-color: rgb(255, 255, 255); font-family:=
sans-serif; font-size: 13px; line-height: 19px; ">=85"</span></a></div><di=
v><br></div><div>Meanwhile, languages such as Rust aim to prohibit dangling=
pointers.</div></div><div><br></div><div><br><blockquote type=3D"cite">On =
Saturday, June 15, 2013 5:21:58 PM UTC-7, carrieran...@<a href=3D"http://ya=
hoo.co.uk">yahoo.co.uk</a> wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex=
;">On Saturday, June 15, 2013 3:26:36 PM UTC-4, Nicol Bolas wrote:<blockquo=
te class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1p=
x #ccc solid;padding-left:1ex">I'm in total agreement with Nevin on this: t=
his is a complete deal-breaker.<br><br>What is the most common operation pe=
rformed on an arbitrary range of contiguously-allocated elements? Iteration=
=85<snip><br></blockquote><div><br></div><div>I've said it in multipl=
e ways, including in the text you quoted: <b>A sequence is not an iterator.=
</b></div></blockquote><br>You're right, sequences aren't iterators.<br><br=
>But I never said that they were, so your statement is a non-sequitur. I sa=
id that the most common operation that someone would perform on a sequence =
would be <i>iteration</i>, but iteration does not require or even imply the=
use of an iterator. The most common operation people do on a `vector` or a=
rray is iteration too; that doesn't make them iterators.<br><br><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div>So I don't regard it as good example=
.. Real examples are better.</div><div><br></div><div>So an actual impl=
ementation might take the form:</div><div><br></div><div><div style=3D"back=
ground-color:rgb(250,250,250);border:1px solid rgb(187,187,187);word-wrap:b=
reak-word"><code><span style=3D"color:#008">void</span> func<span style=3D"=
color:#660">(</span>std<span style=3D"color:#660">::</span>sequence<span st=
yle=3D"color:#080"><int></span> sq<span style=3D"color:#660">)</span>=
<span style=3D"color:#660">{</span><br> process<span style=3D"color:#=
660">(</span>sq<span style=3D"color:#660">);</span><br><span style=3D"color=
:#660">}</span></code></div><div><br></div></div><div>or</div><div><br></di=
v><div><div style=3D"background-color:rgb(250,250,250);border:1px solid rgb=
(187,187,187);word-wrap:break-word"><code><span style=3D"color:#008">void</=
span> func<span style=3D"color:#660">(</span>std<span style=3D"color:#660">=
::</span>sequence<span style=3D"color:#080"><int></span> sq<span styl=
e=3D"color:#660">)</span> <span style=3D"color:#660">{</span><br> <spa=
n style=3D"color:#008">for</span> <span style=3D"color:#660">(</span><span =
style=3D"color:#008">auto</span><span style=3D"color:#660">&</span> at<=
span style=3D"color:#660">:</span>sq<span style=3D"color:#660">)</span><br>=
process<span style=3D"color:#660">(</span>at<span style=3D"color:#66=
0">);</span><br><span style=3D"color:#660">}</span><br></code></div><br></d=
iv></blockquote><div><br>The problem with these "solutions" is that they do=
n't actually solve the problem; not the problem that was outlined. The orig=
inal example code very clearly stated that `process` took <i>two sequences<=
/i>. The sole purpose of `func` was therefore to split a single sequence ar=
bitrarily for consumption by `process`.<br><br>Since your examples don't ac=
tually do the same thing, they're invalid solutions to the problem at hand.=
<br></div></blockquote><div><br></div><div>I did note when I deviated, and =
I did agree that in some cases it does require additional logic. I then exp=
lained how that additional logic generally tends to simplify programs as a =
whole because it allows you to remove logic from other parts of your progra=
m -- who tests the address of a parameter passed by reference? Just move th=
e logic to where it needs to be and it tends to simplify the program. I the=
n reaffirmed that sequences are not designed to replace other types, like i=
ncreasing the vocabulary of a language.</div><br><blockquote type=3D"cite">=
<div><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0=
px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); bo=
rder-left-style: solid; padding-left: 1ex; position: static; z-index: auto;=
"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex">So why should we go against <i>d=
ecades</i> of user experience here?<br></blockquote><div><br></div><div>Let=
's not overstate -- References were introduced 30 years ago.</div></blockqu=
ote><div><br>And yet, virtually every C++ object has value semantics. Imagi=
ne that; after 30 years, we're still using objects with value semantics.<br=
><br>Furthermore, my comment was in response to the lack of a valid empty s=
tate, not to your by-reference reference* semantics. These are in fact sepa=
rate issues; you can still have your by-reference reference semantics while=
defining the empty state as valid.<br></div></blockquote><div><br></div><d=
iv>So what do you think is ideal for this type? Based on our exchanges, I a=
m led to believe you favor "pointer semantics" -- where (re)assignment and =
null are qualities worth debating in favor of.</div><br><blockquote type=3D=
"cite"><div>*: Not a typo. "By-reference reference" means that the object f=
unctions like a C++ reference (thus "by-reference"), and the object concept=
ually acts as a reference to another object (the second "reference") that i=
t does not own. This is to distinguish your "sequence" type from "by-value =
reference" types like `shared_ptr`. There, the object itself works by value=
(you can assign to it), but the object acts as a reference to another obje=
ct that it does not (fully) own.<br><br></div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-=
left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">And speaking of dec=
ades of experience, that applies to the whole "immutable reference semantic=
s" thing too. Pretty much every object in the C++ standard library since C+=
+98 uses <i>value</i> semantics. Even the istreams work by value-move; they=
just forbid copying. They're mutable by default; if you want them to be im=
mutable, you make them `const`. That's the <i>standard</i>.<br><br>The only=
objects that don't use pure value semantics are those that explicitly refe=
rence things. And even those are by-<i>value</i> references: std::reference=
_wrapper can be re-seated, as can std::shared_ptr, and any other standard l=
ibrary reference-to-thing object.<br><br>So again, why should we go against=
how all other objects in the standard work? You've proven to yourself that=
such an implementation <i>can</i> work and <i>can</i> be useful. That's gr=
eat. But that's not enough to say that it <i>should</i> be done, or that it=
should become <i>standardized</i>.</blockquote><div> </div><div>And I=
acknowledged that I expected resistance to the idea of reference-like sema=
ntics, and was offered to put out an implementation which supports both mod=
es. We'll have to wait and see how it goes.</div></blockquote><div><br=
>My ultimate point here is this: If you take those out, your proposal is no=
different from `array_ref` besides the name. So why would yours succeed wh=
ere array_ref failed?<br></div></blockquote><div><br></div><div>A big point=
is that array_ref does not represent mutable elements. Sequences *do* repr=
esent mutable elements. That's a huge difference, IMO. The implementation I=
am working also has some things which increase type safety. You asked me t=
his at the previous revision and I answered you in detail -- about 1.5=
pages. I also mentioned sequence_n<>, octet_sequence, etc. in this r=
ev.</div><div><br></div><div>As to why they might accept this after rejecti=
ng array_ref: Reference-like semantics are still an option, and there are s=
till several differences. If llvm found a need for mutable array refs just =
last year=85 well, I may have more code that relies on this type than their=
s. It could be different enough from array_ref and perhaps more refined tha=
n array_ref that it may be worth consideration. I also see disappointment t=
hat array_ref did not pass. I'm actually quite curious as to what the reaso=
n for rejection was. Finally, array_ref has been dormant for a while... and=
how far away are ranges?</div><div><br></div></div>Thanks<div><br></div></=
body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--Apple-Mail=_C3F2FF8A-1F52-477B-BB44-8BC8F48A82C6--
.
Author: Chris Jefferson <chris@bubblescope.net>
Date: Sun, 16 Jun 2013 11:00:11 +0100
Raw View
This is a multi-part message in MIME format.
--------------060709070205080901040008
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
On 16/06/13 10:45, justin carlson wrote:
>> The entire rest of the world disagrees with you.
>
> echo "Let's not overstate"
>
>
>> Virtually every API that takes a sequence of contiguously allocated
>> objects will accept an empty sequence thereof, regardless of how that
>> API might define an empty sequence.
>
> This is also an overstatement. I explained why this is often an error,
> as well as reminded you that you would still have all the mechanisms
> you have today to express the intention where an input may be
> effectively null or empty. Where an author specifies a parameter is a
> sequence and a sequence is forbidden from being empty that states a
> contract very clearly.
>
I'm not sure it's overstating. Thinking of all the libraries and
languages I have ever used, all of them have had a way to create an
empty "sequence" (in whatever way that language represents a sequence,
whether it be an array, container or pair of positions), and in all
those languages, operating on that empty sequence (for example sorting
it) is well-defined.
I could, if you like, produce a concrete list of all the languages and
libraries were sorting or iterating over an empty "sequence" is
well-defined. I can't think of any of the top of my head where it is not.
Chris
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--------------060709070205080901040008
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=windows-1252"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 16/06/13 10:45, justin carlson
wrote:<br>
</div>
<blockquote
cite="mid:AA14A4DF-D546-4854-9C6C-6F5B591F0E87@yahoo.co.uk"
type="cite">
<div><font face="helvetica"><span style="font-size: 13px;"></span></font>
<blockquote type="cite">The entire rest of the world disagrees
with you.</blockquote>
<div><br>
</div>
<div>echo "Let's not overstate"</div>
<div><br>
</div>
<br>
<blockquote type="cite">Virtually every API that takes a
sequence of contiguously allocated objects will accept an
empty sequence thereof, regardless of how that API might
define an empty sequence.<br>
</blockquote>
<div><br>
</div>
<div>This is also an overstatement. I explained why this is
often an error, as well as reminded you that you would still
have all the mechanisms you have today to express the
intention where an input may be effectively null or empty.
Where an author specifies a parameter is a sequence and a
sequence is forbidden from being empty that states a contract
very clearly.</div>
<br>
</div>
</blockquote>
<br>
I'm not sure it's overstating. Thinking of all the libraries and
languages I have ever used, all of them have had a way to create an
empty "sequence" (in whatever way that language represents a
sequence, whether it be an array, container or pair of positions),
and in all those languages, operating on that empty sequence (for
example sorting it) is well-defined.<br>
<br>
I could, if you like, produce a concrete list of all the languages
and libraries were sorting or iterating over an empty "sequence" is
well-defined. I can't think of any of the top of my head where it is
not.<br>
<br>
Chris<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
<br />
<br />
--------------060709070205080901040008--
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Sun, 16 Jun 2013 13:22:38 +0200
Raw View
On Thu, Jun 13, 2013 at 8:58 PM, <carrierandoperator@yahoo.co.uk> wrote:
> On Thursday, June 13, 2013 1:09:01 PM UTC-4, Olaf van der Spek wrote:
>>
>> I'd still go for a (iterator) range concept instead of a 'sequence'
>> concept.
>
>
> Questions on my mind: What is the status of Ranges? Is there a current
I'd love to know, perhaps a member of the Ranges SG could provide an update?
> proposal that people are agreeing on? Is it being improved and does it have
> open consideration for standardization in its current form? Is it based on
> Boost?
>
> I've found a (quiet) mailing list: http://www.open-std.org/pipermail/ranges/
>
> I also ran across a document by Jeffrey Yasskin from jan.2012:
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html
>
> As well as some mentions in the lists.
>
> If ranges are coming along well, there is likely one source I can go to
> which would answer all these questions. Unfortunately, I cannot find that.
> Sorry - I am new here =\
>
> Prior to reviewing the range proposal: A range implementation could be made
> to be significantly more complex than a representation of contiguous
> elements (sequence). If the range proposal exists and happens to be complex,
> then it might generally be regarded as a distinct type which is aimed at
> solving a different problem.
While the proposal and implementation might be a bit more complex, the
interface of for example boost::iterator_range seems quite simple.
If the interfaces are similar I'd say it's not a distinct type solving
a distinct problem.
--
Olaf
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Sun, 16 Jun 2013 13:26:50 +0200
Raw View
On Sat, Jun 15, 2013 at 9:26 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> And speaking of decades of experience, that applies to the whole "immutable
> reference semantics" thing too. Pretty much every object in the C++ standard
> library since C++98 uses value semantics. Even the istreams work by
> value-move; they just forbid copying. They're mutable by default; if you
> want them to be immutable, you make them `const`. That's the standard.
Types like (boost) iterator_range, array_ref and string_view are used
for function parameters a lot. Having const by default for such
parameters makes sense, IMO.
I've been wondering about having references default to const too, but
it's far too late to change that.
--
Olaf
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Sun, 16 Jun 2013 07:26:54 -0400
Raw View
--Apple-Mail=_490FA42E-4CEA-4391-B19E-5D1ED387EBBC
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=windows-1252
On Jun 16, 2013, at 4:23 AM, Chris Jefferson <chris@bubblescope.net> wrote:
> On 15/06/13 00:22, carrierandoperator@yahoo.co.uk wrote:
>>=20
>> 3. Why impose that size > 0 ?
>>=20
>> In my implementation, empty sequences are forbidden. That is by design. =
I've lived with this constraint in my implementation for years and have no =
desire or need to permit empty sequences in that implementation. I don't co=
nsider it a nuisance, but an aid. It increases memory safety, and provides =
narrow semantics similar to references.
>>=20
>=20
> Reasons to allow empty sequences.
>=20
> 1) The closest thing we have to sequences in C++ (pair of iterators), alr=
eady support empty sequences. The following compiles fine (sorry, making up=
method names and abusing notation)
>=20
> std::vector<int> v;
> std::sort(v.begin(), v.end());=20
>=20
> In a 'sequence' world, I assume the following would be undefined behaviou=
r:
>=20
> std::vector<int> v;
> std::seq_sort(v);
Either UB or throw -- whichever is the least surprising. If empty sequences=
are forbidden, then you would need to write
Either
if (!v.empty())
seq_sort(v);
Or
try {
seq_sort(v);
}
catch (std::logic_error& e) { // << that's the exception thrown in its pre=
sent draft form
std::cout << "oops: " << e.what() << std::endl;
...
}
> I had a quick look for some code where empty ranges would be useful:
>=20
> When ranges/sequences are more popular, I would really like to do things =
like:
>=20
> seq_print(seq_filter(v, function));
>=20
> Would this be undefined if all elements of 'v' were rejected by 'function=
'. That would be unfortunate.
Also either UB or an exception if that is the form =85and inferring the typ=
e parameters and results from your question, while assuming `v` were not em=
pty. However, if you wanted that syntax -- it would generally be illogical =
to return a slice of a sequence of a filtered input parameter because it on=
ly represents contiguous elements (your intent was to suggest that seq_filt=
er returned a slice/sequence, correct?). Rather than return a slice, it wou=
ld usually make sense to return filtered results as a vector/set of indices=
or values. In that case, you would have either a) a vector/set of pointers=
or b) a vector/set of indices and the input sequence. But you can achieve =
a similar effect using:
// made up stuff and absurd notation returned
struct print {
template<typename T>
void operator()(T& p) const {
std::cout << p << ' ';
}
};
template<typename T>
bool is_odd(const T& p) { return p % 2; } // << silly filter
template<typename TSequence, typename TApplier, typename TConditional>
void seq_apply_if(const TSequence& pSequence, const TApplier& pApplier, co=
nst TConditional& pConditional) {
for (auto& at:pSequence) {
if (pConditional(at)) {
pApplier(at);
}
}
}
void foo() {
const int v[] =3D {1, 2, 3, 4, 5, 6, 7, 8, 9};
seq_apply_if(Example::sequence<int>(v), print(), is_odd<int>); // << HERE
std::cout.flush();
}
Even this is quite convenient if you don't face something you should reuse:
const int v[] =3D {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (auto& at:Example::sequence<int>(v)) {
if (at % 2) std::cout << at << ' ';
}
std::cout.flush();
But yes, funneling function results of sequences in the form you provided w=
ould require a break of sorts where a sentinel were reachable.
> Chris
>=20
>=20
>=20
> --=20
> =20
> ---=20
> You received this message because you are subscribed to a topic in the Go=
ogle Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.=
org/d/topic/std-proposals/r5rYVkTXfhg/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to std-p=
roposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at http://groups.google.com/a/isocpp.org/group/std-propo=
sals/.
> =20
> =20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_490FA42E-4CEA-4391-B19E-5D1ED387EBBC
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=windows-1252
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dwindows-1252"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-=
mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Jun =
16, 2013, at 4:23 AM, Chris Jefferson <<a href=3D"mailto:chris@bubblesco=
pe.net">chris@bubblescope.net</a>> wrote:</div><br class=3D"Apple-interc=
hange-newline"><blockquote type=3D"cite">
=20
<meta content=3D"text/html; charset=3Dwindows-1252" http-equiv=3D"Conte=
nt-Type">
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 15/06/13 00:22,
<a class=3D"moz-txt-link-abbreviated" href=3D"mailto:carrierandoperat=
or@yahoo.co.uk">carrierandoperator@yahoo.co.uk</a> wrote:<br>
</div>
<blockquote cite=3D"mid:48e02950-675c-45af-a74b-2bb6a4831443@isocpp.org=
" type=3D"cite"><br>
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div>3. Why impose that size > 0 ?</div>
</blockquote>
<div><br>
</div>
<div>In my implementation, empty sequences are forbidden. That is
by design. I've lived with this constraint in my implementation
for years and have no desire or need to permit empty sequences
in that implementation. I don't consider it a nuisance, but an
aid. It increases memory safety, and provides narrow semantics
similar to references.</div>
<div><br>
</div>
</blockquote>
<br>
Reasons to allow empty sequences.<br>
<br>
1) The closest thing we have to sequences in C++ (pair of
iterators), already support empty sequences. The following compiles
fine (sorry, making up method names and abusing notation)<br>
<br>
std::vector<int> v;<br>
std::sort(v.begin(), v.end()); <br>
<br>
In a 'sequence' world, I assume the following would be undefined
behaviour:<br>
<br>
std::vector<int> v;<br>
std::seq_sort(v);<br></div></blockquote><div><br></div><div>Either UB o=
r throw -- whichever is the least surprising. If empty sequences are forbid=
den, then you would need to write</div><div><br></div><div><div>Either</div=
><div><font face=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"wh=
ite-space:pre"> </span>if (!v.empty())</font></div><div><font face=3D"Couri=
er New"><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>&n=
bsp;seq_sort(v);</font></div><div><br></div><div><br></div><div>Or</div><di=
v><font face=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"white-=
space:pre"> </span>try {</font></div><div><font face=3D"Courier New"><span =
class=3D"Apple-tab-span" style=3D"white-space:pre"> </span> seq_sort(v=
);</font></div><div><font face=3D"Courier New"><span class=3D"Apple-tab-spa=
n" style=3D"white-space:pre"> </span>}</font></div><div><font face=3D"Couri=
er New"><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>ca=
tch (std::logic_error& e) { // << that's the exception thrown in =
its present draft form</font></div><div><font face=3D"Courier New"><span cl=
ass=3D"Apple-tab-span" style=3D"white-space:pre"> </span> std::cout &l=
t;< "oops: " << e.what() << std::endl;</font></div><div><fon=
t face=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"white-space:=
pre"> </span> ...</font></div><div><font face=3D"Courier New"><span cl=
ass=3D"Apple-tab-span" style=3D"white-space:pre"> </span>}</font></div><div=
><br></div></div><div><br></div><br><blockquote type=3D"cite"><div bgcolor=
=3D"#FFFFFF" text=3D"#000000">I had a quick look for some code where empty =
ranges would be useful:<br>
<br>
When ranges/sequences are more popular, I would really like to do
things like:<br>
<br>
seq_print(seq_filter(v, function));<br>
<br>
Would this be undefined if all elements of 'v' were rejected by
'function'. That would be unfortunate.<br></div></blockquote><div><br><=
/div><div>Also either UB or an exception if that is the form =85and inferri=
ng the type parameters and results from your question, while assuming `v` w=
ere not empty. However, if you wanted that syntax -- it would generally be =
illogical to return a slice of a sequence of a filtered input parameter bec=
ause it only represents contiguous elements (your intent was to suggest tha=
t seq_filter returned a slice/sequence, correct?). Rather than return a sli=
ce, it would usually make sense to return filtered results as a vector/set =
of indices or values. In that case, you would have either a) a vector/set o=
f pointers or b) a vector/set of indices and the input sequence. But you ca=
n achieve a similar effect using:</div><div><br></div><div><span class=3D"A=
pple-tab-span" style=3D"white-space:pre"> </span>// made up stuff and=
absurd notation returned</div><div><div><font face=3D"Courier New"><span c=
lass=3D"Apple-tab-span" style=3D"white-space:pre"> </span>struct print {</f=
ont></div><div></div><div><font face=3D"Courier New"><span class=3D"Apple-t=
ab-span" style=3D"white-space:pre"> </span> template<typename T>=
</font></div><div><font face=3D"Courier New"><span class=3D"Apple-tab-span"=
style=3D"white-space:pre"> </span> void operator()(T& p) const {<=
/font></div><div><font face=3D"Courier New"><span class=3D"Apple-tab-span" =
style=3D"white-space:pre"> </span> std::cout << p <<=
' ';</font></div><div><font face=3D"Courier New"><span class=3D"Apple-tab-=
span" style=3D"white-space:pre"> </span> }</font></div><div><font face=
=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"white-space:pre"> =
</span>};</font></div><div><font face=3D"Courier New"><br></font></div><div=
><font face=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"white-s=
pace:pre"> </span>template<typename T></font></div><div><font face=3D=
"Courier New"><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </s=
pan>bool is_odd(const T& p) { return p % 2; } // << sil=
ly filter</font></div><div><font face=3D"Courier New"><br></font></div><div=
><font face=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"white-s=
pace:pre"> </span>template<typename TSequence, typename TApplier, typena=
me TConditional></font></div><div><font face=3D"Courier New"><span class=
=3D"Apple-tab-span" style=3D"white-space:pre"> </span>void seq_apply_if(con=
st TSequence& pSequence, const TApplier& pApplier, const TCondition=
al& pConditional) {</font></div><div><font face=3D"Courier New"><span c=
lass=3D"Apple-tab-span" style=3D"white-space:pre"> </span> for (auto&a=
mp; at:pSequence) {</font></div><div><font face=3D"Courier New"><span class=
=3D"Apple-tab-span" style=3D"white-space:pre"> </span> if (pCond=
itional(at)) {</font></div><div><font face=3D"Courier New"><span class=3D"A=
pple-tab-span" style=3D"white-space:pre"> </span> pApplier(at);=
</font></div><div><font face=3D"Courier New"><span class=3D"Apple-tab-span"=
style=3D"white-space:pre"> </span> }</font></div><div><font fac=
e=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"white-space:pre">=
</span> }</font></div><div><font face=3D"Courier New"><span class=3D"=
Apple-tab-span" style=3D"white-space:pre"> </span>}</font></div><div><font =
face=3D"Courier New"><br></font></div><div><font face=3D"Courier New"><span=
class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>void foo() {</f=
ont></div><div><font face=3D"Courier New"><span class=3D"Apple-tab-span" st=
yle=3D"white-space:pre"> </span> const int v[] =3D {1, 2, 3, 4, 5, 6, =
7, 8, 9};</font></div><div><font face=3D"Courier New"><span class=3D"Apple-=
tab-span" style=3D"white-space:pre"> </span> seq_apply_if(Example::seq=
uence<int>(v), print(), is_odd<int>); // << HERE</font></=
div><div><font face=3D"Courier New"><span class=3D"Apple-tab-span" style=3D=
"white-space:pre"> </span> std::cout.flush();</font></div><div><font f=
ace=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"white-space:pre=
"> </span>}</font></div><div><br></div><div>Even this is quite convenient i=
f you don't face something you should reuse:</div><div><br></div><div><div>=
<font face=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"white-sp=
ace:pre"> </span>const int v[] =3D {1, 2, 3, 4, 5, 6, 7, 8, 9};</font></div=
><div><font face=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"wh=
ite-space:pre"> </span>for (auto& at:Example::sequence<int>(v)) {=
</font></div><div><font face=3D"Courier New"><span class=3D"Apple-tab-span"=
style=3D"white-space:pre"> </span> if (at % 2) std::cout << at =
<< ' ';</font></div><div><font face=3D"Courier New"><span class=3D"Ap=
ple-tab-span" style=3D"white-space:pre"> </span>}</font></div><div><font fa=
ce=3D"Courier New"><span class=3D"Apple-tab-span" style=3D"white-space:pre"=
> </span>std::cout.flush();</font></div></div><div><br></div></div><div>But=
yes, funneling function results of sequences in the form you provided woul=
d require a break of sorts where a sentinel were reachable.</div><div><br><=
/div><br><blockquote type=3D"cite"><div bgcolor=3D"#FFFFFF" text=3D"#000000=
">Chris<br>
<br>
<br>
</div><div><br class=3D"webkit-block-placeholder"></div>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/r5rYVkTXfhg/unsubscribe">https://groups.=
google.com/a/isocpp.org/d/topic/std-proposals/r5rYVkTXfhg/unsubscribe</a>.<=
br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@=
isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br>
<br>
<br>
</blockquote></div><br></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--Apple-Mail=_490FA42E-4CEA-4391-B19E-5D1ED387EBBC--
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Sun, 16 Jun 2013 14:58:32 -0400
Raw View
--Apple-Mail=_EE06FFC3-8FBF-4992-8E76-770C82EC1840
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1
On Jun 16, 2013, at 6:00 AM, Chris Jefferson <chris@bubblescope.net> wrote:
> On 16/06/13 10:45, justin carlson wrote:
>>> The entire rest of the world disagrees with you.
>>=20
>> echo "Let's not overstate"
>>=20
>>=20
>>> Virtually every API that takes a sequence of contiguously allocated obj=
ects will accept an empty sequence thereof, regardless of how that API migh=
t define an empty sequence.
>>=20
>> This is also an overstatement. I explained why this is often an error, a=
s well as reminded you that you would still have all the mechanisms you hav=
e today to express the intention where an input may be effectively null or =
empty. Where an author specifies a parameter is a sequence and a sequence i=
s forbidden from being empty that states a contract very clearly.
>>=20
>=20
> I'm not sure it's overstating. Thinking of all the libraries and language=
s I have ever used, all of them have had a way to create an empty "sequence=
" (in whatever way that language represents a sequence, whether it be an ar=
ray, container or pair of positions), and in all those languages, operating=
on that empty sequence (for example sorting it) is well-defined.
>=20
> I could, if you like, produce a concrete list of all the languages and li=
braries were sorting or iterating over an empty "sequence" is well-defined.=
I can't think of any of the top of my head where it is not.
I read it as (paraphrased): Virtually every API that takes an array as a pa=
rameter will accept an empty array. (Array, or other contiguous allocation =
of objects)
I think of an API "accept"ing this as:
- It would not be an error to pass an empty array.
- It would continue without visible acknowledgement of an error (e.g. no t=
hrow, no assert, no log).
- Passing an empty array would also not result in UB.
- That the results or side effects of passing empty is well defined where =
ambiguous: "median(arr[]) will return -11 if you pass an empty array. it wi=
ll not reset the counter thingie".
- In C family languages, Null is quite commonly used for an empty array pa=
rameter.
So the inverse would be: Virtually no APIs reject or object to empty arrays=
..
So I called "Overstatement" - You think Nicol meant something different?
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_EE06FFC3-8FBF-4992-8E76-770C82EC1840
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Diso-8859-1"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mo=
de: space; -webkit-line-break: after-white-space; "><br><div><div>On Jun 16=
, 2013, at 6:00 AM, Chris Jefferson <<a href=3D"mailto:chris@bubblescope=
..net">chris@bubblescope.net</a>> wrote:</div><br class=3D"Apple-intercha=
nge-newline"><blockquote type=3D"cite">
=20
<meta content=3D"text/html; charset=3Dwindows-1252" http-equiv=3D"Conte=
nt-Type">
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 16/06/13 10:45, justin carlson
wrote:<br>
</div>
<blockquote cite=3D"mid:AA14A4DF-D546-4854-9C6C-6F5B591F0E87@yahoo.co.u=
k" type=3D"cite">
<div><font face=3D"helvetica"><span style=3D"font-size: 13px;"></span=
></font>
<blockquote type=3D"cite">The entire rest of the world disagrees
with you.</blockquote>
<div><br>
</div>
<div>echo "Let's not overstate"</div>
<div><br>
</div>
<br>
<blockquote type=3D"cite">Virtually every API that takes a
sequence of contiguously allocated objects will accept an
empty sequence thereof, regardless of how that API might
define an empty sequence.<br>
</blockquote>
<div><br>
</div>
<div>This is also an overstatement. I explained why this is
often an error, as well as reminded you that you would still
have all the mechanisms you have today to express the
intention where an input may be effectively null or empty.
Where an author specifies a parameter is a sequence and a
sequence is forbidden from being empty that states a contract
very clearly.</div>
<br>
</div>
</blockquote>
<br>
I'm not sure it's overstating. Thinking of all the libraries and
languages I have ever used, all of them have had a way to create an
empty "sequence" (in whatever way that language represents a
sequence, whether it be an array, container or pair of positions),
and in all those languages, operating on that empty sequence (for
example sorting it) is well-defined.<br>
<br>
I could, if you like, produce a concrete list of all the languages
and libraries were sorting or iterating over an empty "sequence" is
well-defined. I can't think of any of the top of my head where it is
not.<br></div></blockquote><div><br></div></div>I read it as (paraphras=
ed): Virtually every API that takes an array as a parameter will accept an =
empty array. (Array, or other contiguous allocation of objects)<div><b=
r></div><div>I think of an API "accept"ing this as:</div><div><br></div><di=
v><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>- It wou=
ld not be an error to pass an empty array.</div><div><span class=3D"Apple-t=
ab-span" style=3D"white-space:pre"> </span>- It would continue without=
visible acknowledgement of an error (e.g. no throw, no assert, no log).</d=
iv><div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>- =
Passing an empty array would also not result in UB.</div><div><span class=
=3D"Apple-tab-span" style=3D"white-space:pre"> </span>- That the results or=
side effects of passing empty is well defined where ambiguous: "median(arr=
[]) will return -11 if you pass an empty array. it will not reset the count=
er thingie".</div><div><span class=3D"Apple-tab-span" style=3D"white-space:=
pre"> </span>- In C family languages, Null is quite commonly used for an em=
pty array parameter.<br><div><br></div></div><div>So the inverse would be: =
Virtually no APIs reject or object to empty arrays.</div><div><br></div><di=
v>So I called "Overstatement" - You think Nicol meant something differ=
ent?</div><div><br></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--Apple-Mail=_EE06FFC3-8FBF-4992-8E76-770C82EC1840--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 16 Jun 2013 12:26:22 -0700 (PDT)
Raw View
------=_Part_2086_7526229.1371410782328
Content-Type: text/plain; charset=ISO-8859-1
On Sunday, June 16, 2013 11:58:32 AM UTC-7, justin carlson wrote:
>
> On Jun 16, 2013, at 6:00 AM, Chris Jefferson <ch...@bubblescope.net<javascript:>>
> wrote:
>
> On 16/06/13 10:45, justin carlson wrote:
>
> The entire rest of the world disagrees with you.
>
>
> echo "Let's not overstate"
>
>
> Virtually every API that takes a sequence of contiguously allocated
> objects will accept an empty sequence thereof, regardless of how that API
> might define an empty sequence.
>
>
> This is also an overstatement. I explained why this is often an error,
> as well as reminded you that you would still have all the mechanisms you
> have today to express the intention where an input may be effectively null
> or empty. Where an author specifies a parameter is a sequence and a
> sequence is forbidden from being empty that states a contract very clearly.
>
>
> I'm not sure it's overstating. Thinking of all the libraries and languages
> I have ever used, all of them have had a way to create an empty "sequence"
> (in whatever way that language represents a sequence, whether it be an
> array, container or pair of positions), and in all those languages,
> operating on that empty sequence (for example sorting it) is well-defined.
>
> I could, if you like, produce a concrete list of all the languages and
> libraries were sorting or iterating over an empty "sequence" is
> well-defined. I can't think of any of the top of my head where it is not.
>
>
> I read it as (paraphrased): Virtually every API that takes an array as a
> parameter will accept an empty array. (Array, or other contiguous
> allocation of objects)
>
> I think of an API "accept"ing this as:
>
> - It would not be an error to pass an empty array.
> - It would continue without visible acknowledgement of an error (e.g. no
> throw, no assert, no log).
> - Passing an empty array would also not result in UB.
> - That the results or side effects of passing empty is well defined where
> ambiguous: "median(arr[]) will return -11 if you pass an empty array. it
> will not reset the counter thingie".
> - In C family languages, Null is quite commonly used for an empty array
> parameter.
>
I would generally agree with that assessment. Though if #4 were to happen,
that would almost certainly be a standard library issue. Functions should
not behave ambiguously in the presence of valid parameters. And if those
parameters were invalid, they would have been listed as preconditions, thus
triggering #3: undefined behavior.
And I'm not sure what the last point is getting at. Sure, a NULL pointer is
often used as the begin or end iterators of a range. But in those cases,
both the beginning and end pointers will be NULL, so the size will be zero.
Or there will be an explicit size parameter, which will be zero. So I don't
know where you're going with that.
So the inverse would be: Virtually no APIs reject or object to empty arrays.
>
> So I called "Overstatement" - You think Nicol meant something different?
>
If it is true that "Virtually no APIs reject or object to empty arrays" is
an overstatement, then there would have to be some non-trivial number of
standard library APIs that do one of the following:
1. Error when given an empty array.
2. Visibly acknowledge an empty array, such as by asserting, logging, or
throwing an exception.
3. Exhibit undefined behavior on an empty array, as specified by the
standard (or has ambiguous behavior, likely a standard library issue).
I don't know of any standard library functions that accept ranges for which
any of these is true. I know of functions that might trigger your #5 NULL
condition, but those are almost always "output iterators" of some kind,
which are not really ranges or sequences of values; they're a place to
write data. And many of them are unbounded (ie: it doesn't take a specific
size, just a pointer to write stuff to).
And since I said "Virtually", you need to find more than one or two
counterexamples.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2086_7526229.1371410782328
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Sunday, June 16, 2013 11:58:32 AM UTC-7, justin carlson wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div=
><div>On Jun 16, 2013, at 6:00 AM, Chris Jefferson <<a href=3D"javascrip=
t:" target=3D"_blank" gdf-obfuscated-mailto=3D"1Ioc0EtCGVcJ">ch...@bubblesc=
ope.net</a>> wrote:</div><blockquote type=3D"cite">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>On 16/06/13 10:45, justin carlson
wrote:<br>
</div>
<blockquote type=3D"cite">
<div><font face=3D"helvetica"><span style=3D"font-size:13px"></span><=
/font>
<blockquote type=3D"cite">The entire rest of the world disagrees
with you.</blockquote>
<div><br>
</div>
<div>echo "Let's not overstate"</div>
<div><br>
</div>
<br>
<blockquote type=3D"cite">Virtually every API that takes a
sequence of contiguously allocated objects will accept an
empty sequence thereof, regardless of how that API might
define an empty sequence.<br>
</blockquote>
<div><br>
</div>
<div>This is also an overstatement. I explained why this is
often an error, as well as reminded you that you would still
have all the mechanisms you have today to express the
intention where an input may be effectively null or empty.
Where an author specifies a parameter is a sequence and a
sequence is forbidden from being empty that states a contract
very clearly.</div>
<br>
</div>
</blockquote>
<br>
I'm not sure it's overstating. Thinking of all the libraries and
languages I have ever used, all of them have had a way to create an
empty "sequence" (in whatever way that language represents a
sequence, whether it be an array, container or pair of positions),
and in all those languages, operating on that empty sequence (for
example sorting it) is well-defined.<br>
<br>
I could, if you like, produce a concrete list of all the languages
and libraries were sorting or iterating over an empty "sequence" is
well-defined. I can't think of any of the top of my head where it is
not.<br></div></blockquote><div><br></div></div>I read it as (paraphras=
ed): Virtually every API that takes an array as a parameter will accept an =
empty array. (Array, or other contiguous allocation of objects)<div><b=
r></div><div>I think of an API "accept"ing this as:</div><div><br></div><di=
v><span style=3D"white-space:pre"> </span>- It would not be an error to pas=
s an empty array.</div><div><span style=3D"white-space:pre"> </span>- =
It would continue without visible acknowledgement of an error (e.g. no thro=
w, no assert, no log).</div><div><span style=3D"white-space:pre"> </span>- =
Passing an empty array would also not result in UB.</div><div><span style=
=3D"white-space:pre"> </span>- That the results or side effects of passing =
empty is well defined where ambiguous: "median(arr[]) will return -11 if yo=
u pass an empty array. it will not reset the counter thingie".</div><div><s=
pan style=3D"white-space:pre"> </span>- In C family languages, Null is quit=
e commonly used for an empty array parameter.<br></div></div></blockquote><=
div><br>I would generally agree with that assessment. Though if #4 were to =
happen, that would almost certainly be a standard library issue. Functions =
should not behave ambiguously in the presence of valid parameters. And if t=
hose parameters were invalid, they would have been listed as preconditions,=
thus triggering #3: undefined behavior.<br><br>And I'm not sure what the l=
ast point is getting at. Sure, a NULL pointer is often used as the begin or=
end iterators of a range. But in those cases, both the beginning and end p=
ointers will be NULL, so the size will be zero. Or there will be an explici=
t size parameter, which will be zero. So I don't know where you're going wi=
th that.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div sty=
le=3D"word-wrap:break-word"><div><div></div></div><div>So the inverse would=
be: Virtually no APIs reject or object to empty arrays.</div><div><br></di=
v><div>So I called "Overstatement" - You think Nicol meant something d=
ifferent?</div></div></blockquote><div><br>If it is true that "Virtually no=
APIs reject or object to empty arrays" is an overstatement, then there wou=
ld have to be some non-trivial number of standard library APIs that do one =
of the following:<br><br>1. Error when given an empty array.<br>2. Visibly =
acknowledge an empty array, such as by asserting, logging, or throwing an e=
xception.<br>3. Exhibit undefined behavior on an empty array, as specified =
by the standard (or has ambiguous behavior, likely a standard library issue=
).<br><br>I don't know of any standard library functions that accept ranges=
for which any of these is true. I know of functions that might trigger you=
r #5 NULL condition, but those are almost always "output iterators" of some=
kind, which are not really ranges or sequences of values; they're a place =
to write data. And many of them are unbounded (ie: it doesn't take a specif=
ic size, just a pointer to write stuff to).<br><br>And since I said "Virtua=
lly", you need to find more than one or two counterexamples.<br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_2086_7526229.1371410782328--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 16 Jun 2013 13:13:38 -0700 (PDT)
Raw View
------=_Part_2116_9567921.1371413618587
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
On Sunday, June 16, 2013 2:45:04 AM UTC-7, justin carlson wrote:
>
>
> On Jun 15, 2013, at 10:55 PM, Nicol Bolas <jmck...@gmail.com <javascript:=
>>=20
> wrote:
>
> These are very easy (local) logic errors. Nevertheless, you are writing a=
s=20
> though I strongly oppose throwing in this scenario. I'll quote myself:
>
> Alex B: =85will result in undefined behavior if the vector is empty?
> Me: Either that or throw an exception. Whichever response would be least=
=20
> surprising.
>
> Exceptions were touched on. I feel my stance was one which does not need=
=20
> strong opposition (you can't distance yourself far from me if I am near t=
he=20
> middle). I also calmly reintroduced throwing as a possibility where you=
=20
> disregarded those words in your previous post (when you said "The way you=
=20
> want it=85"). Why distort my words to build an argument that is based on=
=20
> fallacy?
>
Because it's *your proposal*. Yes, you said that it *could* throw an=20
exception. But that's a far cry from saying that it *will* throw an=20
exception. Until you stop dithering over it and actually *decide* whether=
=20
it throws or has undefined behavior, I cannot assume that it will throw.=20
And therefore, if I am to evaluate the proposal, I must assume that it does=
=20
not (since the proposal *doesn't* say that it does).
The question is not "could it throw," but *does* it throw. What does your=
=20
proposal intend to *specify*?
If reference semantics are considered favorable, then it would seem=20
> essential that empty is forbidden. No?
>
No, it's not.
A pointer being NULL means that the pointer is in an invalid state. It does=
=20
not refer to a valid memory address which you can use. Part of the concept=
=20
of a pointer is that it is a value which references another object, but=20
that reference can be invalid.
NULL is invalid by fiat: the C++ standard defines that there will be a=20
particular pointer value. That value will be different from all other=20
pointer values. And if if you try to de-reference it in any way, badness=20
occurs.
Whether an empty array is valid or not is *purely* a design choice. It's=20
about how you *choose* to think about arrays.
An empty array is still *useable* in most ways that you use an array. As=20
stated before, the most common thing you want to do with an array is walk=
=20
it from one end to the other. Like this:
for(auto &t : seq)
{ /* do stuff */}
This code is 100% well defined whether `seq` is empty or not. So there are=
=20
many perfectly valid and legitimate ways to use an array that can tolerate=
=20
the array being empty.
Whether you want by-reference reference semantics or by-value reference=20
semantics is completely orthogonal to the question of whether empty=20
sequences of elements are considered valid state. Just like=20
std::reference_wrapper can be reseated, but must refer to an actual object.=
=20
And the standard has already weighed in on that: empty is valid.
Reference semantics are a topic "Open for Discussion", but I think=20
> reference semantics are worth strong consideration because (*I* believe)=
=20
> that's going to do more to improve programs than sticking to pointer=20
> semantics. It's going to offer a more diverse toolset.
>
> When reference semantics are to be applied to an *object* we have a good=
=20
> mechanism to represent that. We also have a good means to express pointer=
=20
> semantics for an object. We have good ways to pass an array using pointer=
=20
> semantics.
>
No, we don't. If we had `array_ref`, we would. But as of now, the only way=
=20
we have to pass an array is with a pointer+size. And that is *not* a "good=
=20
way".
Even if we considered that a "good way", we don't have a by-reference=20
reference alterantive for other things. Where's the std::reference_wrapper=
=20
variant? Where's the unique_ptr variant that always points to valid memory=
=20
and can't be reseated?
The standard doesn't have *any* by-reference objects; even std::thread=20
objects must be explicitly moved around by value.
What makes your one class so special that it needs to be standardized when=
=20
the standard doesn't work that way?
So why should we go against *decades* of user experience here?
>>>>
>>>
>>> Let's not overstate -- References were introduced 30 years ago.
>>>
>>
>> And yet, virtually every C++ object has value semantics. Imagine that;=
=20
>> after 30 years, we're still using objects with value semantics.
>>
>> Furthermore, my comment was in response to the lack of a valid empty=20
>> state, not to your by-reference reference* semantics. These are in fact=
=20
>> separate issues; you can still have your by-reference reference semantic=
s=20
>> while defining the empty state as valid.
>>
>
> So what do you think is ideal for this type? Based on our exchanges, I am=
=20
> led to believe you favor "pointer semantics" -- where (re)assignment and=
=20
> null are qualities worth debating in favor of.
>
What I want is a type that conforms to the standards set down by the C++=20
standard library, not a type that appears very foreign when compared with=
=20
the behavior of every other object in the library. The C++ standard library=
=20
uses value semantics for pretty much everything. Even=20
`std::reference_wrapper` uses value semantics for the object itself; they=
=20
can be reseated.
What I want is the ability to take an arbitrary contiguously-allocated=20
sequence of elements and implicitly convert it into a specific type which=
=20
can be used as an interface between the code that allocates storage for=20
that array and code that *uses* it. This would allow the user to allocate=
=20
their sequence of elements in whatever way they want, without having to=20
burden the consumer of that array with needless details like where it comes=
=20
from.
`array_ref` would do that. And if any potentially-proposed=20
`iterator_range<T*>` were developed that could be implicitly converted from=
=20
*any* contiguously allocated element sequence (with a very clear means of=
=20
adding new types that implicitly convert), that would be fine too.
Your sequence class doesn't do that. It takes that very simple concept and=
=20
It piles on a bunch of stuff on top of it that I don't want. Let me make=20
this perfectly clear:
*I will never write code that takes a sequence of elements that cannot be=
=20
empty. That will never be a part of any contract for any function I ever=20
write.
*
I would be willing to cope with your sequence's by-reference reference=20
semantics if that somehow helped it get standardized (somehow, I rather=20
doubt it). But never-empty is a deal-breaker; it makes the class completely=
=20
useless to me, and I suspect quite a number of other people, considering=20
how nobody is defending this never-empty design.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2116_9567921.1371413618587
Content-Type: text/html; charset=windows-1252
Content-Transfer-Encoding: quoted-printable
On Sunday, June 16, 2013 2:45:04 AM UTC-7, justin carlson wrote:<blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div>=
<br></div><div><div>On Jun 15, 2013, at 10:55 PM, Nicol Bolas <<a href=
=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"LuJmKYJEE6sJ">j=
mck...@gmail.com</a>> wrote:</div><br></div></div></blockquote><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><di=
v><font face=3D"helvetica"><span style=3D"font-size:13px"></span></font><di=
v>These are very easy (local) logic errors. Nevertheless, you are writing a=
s though I strongly oppose throwing in this scenario. I'll quote myself:</d=
iv><div><br></div><div><span style=3D"color:rgb(80,0,80);font-family:Arial,=
Helvetica,sans-serif;font-size:13px;background-color:rgb(255,255,255)">Alex=
B: =85will result in undefined behavior if the vector is empty?</span></di=
v><div>Me: <span style=3D"background-color:rgb(255,255,255);color:rgb(34,34=
,34);font-family:Arial,Helvetica,sans-serif;font-size:13px">Either that or =
throw an exception. Whichever response would be least surprising.</span></d=
iv><div><span style=3D"background-color:rgb(255,255,255);color:rgb(34,34,34=
);font-family:Arial,Helvetica,sans-serif;font-size:13px"><br></span></div><=
div><span style=3D"background-color:rgb(255,255,255);color:rgb(34,34,34);fo=
nt-family:Arial,Helvetica,sans-serif;font-size:13px">Exceptions were touche=
d on. I feel my stance was one which does not need strong opposition (you c=
an't distance yourself far from me if I am near the middle). I also calmly =
reintroduced throwing as a possibility where you disregarded those words in=
your previous post (when you said "The way you want it=85"). Why distort m=
y words to build an argument that is based on fallacy?</span></div></div></=
div></blockquote><div><br>Because it's <i>your proposal</i>. Yes, you said =
that it <i>could</i> throw an exception. But that's a far cry from saying t=
hat it <i>will</i>
throw an exception. Until you stop dithering over it and actually <i>decid=
e</i> whether it throws or has undefined behavior, I cannot assume that
it will throw. And therefore, if I am to evaluate the proposal, I must ass=
ume that it does not (since the proposal <i>doesn't</i> say that it does).<=
br><br>The question is not "could it throw," but <i>does</i> it throw. What=
does your proposal intend to <i>specify</i>?<br><br></div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #c=
cc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div>=
If reference semantics are considered favorable, then it would seem essent=
ial that empty is forbidden. No?</div></div></div></blockquote><div><br>No,=
it's not.<br><br>A pointer being NULL means that the pointer is in an inva=
lid state. It does not refer to a valid memory address which you can use. P=
art of the concept of a pointer is that it is a value which references anot=
her object, but that reference can be invalid.<br><br>NULL is invalid by fi=
at: the C++ standard defines that there will be a particular pointer value.=
That value will be different from all other pointer values. And if if you =
try to de-reference it in any way, badness occurs.<br><br>Whether an empty =
array is valid or not is <i>purely</i> a design choice. It's about how you =
<i>choose</i> to think about arrays.<br><br>An empty array is still <i>usea=
ble</i> in most ways that you use an array. As stated before, the most comm=
on thing you want to do with an array is walk it from one end to the other.=
Like this:<br><br><div class=3D"prettyprint" style=3D"background-color: rg=
b(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bo=
rder-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div c=
lass=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">for</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">t </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> seq</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">/* do stu=
ff */</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an></div></code></div><br>This code is 100% well defined whether `seq` is e=
mpty or not. So there are many perfectly valid and legitimate ways to use a=
n array that can tolerate the array being empty.<br><br>Whether you want by=
-reference reference semantics or by-value reference semantics is completel=
y orthogonal to the question of whether empty sequences of elements are con=
sidered valid state. Just like std::reference_wrapper can be reseated, but =
must refer to an actual object. And the standard has already weighed in on =
that: empty is valid.<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;"><div style=3D"word-wrap:break-word"><div><div> Reference semantics ar=
e a topic "Open for Discussion", but I think reference semantics are worth =
strong consideration because (*I* believe) that's going to do more to impro=
ve programs than sticking to pointer semantics. It's going to offer a more =
diverse toolset.</div><div><br></div><div>When reference semantics are to b=
e applied to an *object* we have a good mechanism to represent that. We als=
o have a good means to express pointer semantics for an object. We have goo=
d ways to pass an array using pointer semantics.</div></div></div></blockqu=
ote><div style=3D"word-wrap:break-word"><br>No, we don't. If we had `array_=
ref`, we would. But as of now, the only way we have to pass an array is wit=
h a pointer+size. And that is <i>not</i> a "good way".<br><br>Even if we co=
nsidered that a "good way", we don't have a by-reference reference alterant=
ive for other things. Where's the std::reference_wrapper variant? Where's t=
he unique_ptr variant that always points to valid memory and can't be resea=
ted?<br><br>The standard doesn't have <i>any</i> by-reference objects; even=
std::thread objects must be explicitly moved around by value.<br><br>What =
makes your one class so special that it needs to be standardized when the s=
tandard doesn't work that way?<br><br><blockquote style=3D"margin: 0px 0px =
0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" c=
lass=3D"gmail_quote"><div><blockquote style=3D"margin: 0px 0px 0px 0.8ex; b=
order-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;" class=3D"gmai=
l_quote" type=3D"cite"><div></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex"><blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex">So why should we go against <i>decades</i> of user experi=
ence here?<br></blockquote><div><br></div><div>Let's not overstate -- Refer=
ences were introduced 30 years ago.</div></blockquote><div><br>And yet, vir=
tually every C++ object has value semantics. Imagine that; after 30 years, =
we're still using objects with value semantics.<br><br>Furthermore, my comm=
ent was in response to the lack of a valid empty state, not to your by-refe=
rence reference* semantics. These are in fact separate issues; you can stil=
l have your by-reference reference semantics while defining the empty state=
as valid.<br></div></blockquote><div><br></div><div>So what do you think i=
s ideal for this type? Based on our exchanges, I am led to believe you favo=
r "pointer semantics" -- where (re)assignment and null are qualities worth =
debating in favor of.</div></div></blockquote></div><div><br>What I want is=
a type that conforms to the standards set down by the C++ standard library=
, not a type that appears very foreign when compared with the behavior of e=
very other object in the library. The C++ standard library uses value seman=
tics for pretty much everything. Even `std::reference_wrapper` uses value s=
emantics for the object itself; they can be reseated.<br><br>What I want is=
the ability to take an arbitrary contiguously-allocated sequence of elemen=
ts and implicitly convert it into a specific type which can be used as an i=
nterface between the code that allocates storage for that array and code th=
at <i>uses</i> it. This would allow the user to allocate their sequence of =
elements in whatever way they want, without having to burden the consumer o=
f that array with needless details like where it comes from.<br><br>`array_=
ref` would do that. And if any potentially-proposed `iterator_range<T*&g=
t;` were developed that could be implicitly converted from <i>any</i> conti=
guously allocated element sequence (with a very clear means of adding new t=
ypes that implicitly convert), that would be fine too.<br><br>Your sequence=
class doesn't do that. It takes that very simple concept and It piles on a=
bunch of stuff on top of it that I don't want. Let me make this perfectly =
clear:<br><br><b>I will never write code that takes a sequence of elements =
that cannot be empty. That will never be a part of any contract for any fun=
ction I ever write.<br></b><br>I would be willing to cope with your sequenc=
e's by-reference reference semantics if that somehow helped it get standard=
ized (somehow, I rather doubt it). But never-empty is a deal-breaker; it ma=
kes the class completely useless to me, and I suspect quite a number of oth=
er people, considering how nobody is defending this never-empty design.</di=
v>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_2116_9567921.1371413618587--
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Sun, 16 Jun 2013 16:33:29 -0400
Raw View
On Jun 16, 2013, at 7:22 AM, Olaf van der Spek <olafvdspek@gmail.com> wrote:
> On Thu, Jun 13, 2013 at 8:58 PM, <carrierandoperator@yahoo.co.uk> wrote:
>> On Thursday, June 13, 2013 1:09:01 PM UTC-4, Olaf van der Spek wrote:
>>>
>>> I'd still go for a (iterator) range concept instead of a 'sequence'
>>> concept.
>>
>>
>> Questions on my mind: What is the status of Ranges? Is there a current
>
> I'd love to know, perhaps a member of the Ranges SG could provide an update?
Ok. Thanks. Hopefully we'll get an update.
>> proposal that people are agreeing on? Is it being improved and does it have
>> open consideration for standardization in its current form? Is it based on
>> Boost?
>>
>> I've found a (quiet) mailing list: http://www.open-std.org/pipermail/ranges/
>>
>> I also ran across a document by Jeffrey Yasskin from jan.2012:
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3350.html
>>
>> As well as some mentions in the lists.
>>
>> If ranges are coming along well, there is likely one source I can go to
>> which would answer all these questions. Unfortunately, I cannot find that.
>> Sorry - I am new here =\
>>
>> Prior to reviewing the range proposal: A range implementation could be made
>> to be significantly more complex than a representation of contiguous
>> elements (sequence). If the range proposal exists and happens to be complex,
>> then it might generally be regarded as a distinct type which is aimed at
>> solving a different problem.
>
> While the proposal and implementation might be a bit more complex, the
> interface of for example boost::iterator_range seems quite simple.
> If the interfaces are similar I'd say it's not a distinct type solving
> a distinct problem.
Hmkay - Suppose we were to use the boost iterator_range, or the std::range in its current form. What would the following look like using those implementations?
/** @brief sets elements values in @a sq */
namespace MyAPI {
void fill(std::mutable_sequence<double> sq); // << extern
}
void foo() {
double a[5];
MyAPI::fill(a);
std::array<double, 5>b;
MyAPI::fill(b);
std::vector<double>c(5);
MyAPI::fill(c);
MyAPI::fill(std::mutable_sequence<double>(c.begin(), c.end())); // note: iterator pair ctor is a 'maybe'
MyAPI::fill(std::mutable_sequence<double>(c.data(), c.size()));
}
void MyAPI::fill(std::mutable_sequence<double> sq) {
for (double& at:sq) at = 7; // set all elements to 7
}
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: carrierandoperator@yahoo.co.uk
Date: Sun, 16 Jun 2013 13:50:31 -0700 (PDT)
Raw View
------=_Part_3169_18016791.1371415831202
Content-Type: text/plain; charset=ISO-8859-1
Notes:
That examples demonstrates how simple it could be for clients to use
MyAPI::fill().
The array_ref proposal mentioned but did formally propose mutability, so
that happens to be an example which array_ref would not be capable of.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3169_18016791.1371415831202
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>Notes:</div><div>That examples demonstrates how simple it could be for=
clients to use MyAPI::fill().</div><div>The array_ref proposal mentioned b=
ut did formally propose mutability, so that happens to be an example which =
array_ref would not be capable of.</div><div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_3169_18016791.1371415831202--
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Sun, 16 Jun 2013 17:34:04 -0400
Raw View
--Apple-Mail=_4F0FE641-1E04-43F5-8310-1B6C62478A93
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1
On Jun 16, 2013, at 3:26 PM, Nicol Bolas <jmckesson@gmail.com> wrote:
> On Sunday, June 16, 2013 11:58:32 AM UTC-7, justin carlson wrote:
> On Jun 16, 2013, at 6:00 AM, Chris Jefferson <ch...@bubblescope.net> wrot=
e:
>> On 16/06/13 10:45, justin carlson wrote:
>>>> The entire rest of the world disagrees with you.
>>>=20
>>> echo "Let's not overstate"
>>>=20
>>>=20
>>>> Virtually every API that takes a sequence of contiguously allocated ob=
jects will accept an empty sequence thereof, regardless of how that API mig=
ht define an empty sequence.
>>>=20
>>> This is also an overstatement. I explained why this is often an error, =
as well as reminded you that you would still have all the mechanisms you ha=
ve today to express the intention where an input may be effectively null or=
empty. Where an author specifies a parameter is a sequence and a sequence =
is forbidden from being empty that states a contract very clearly.
>>>=20
>>=20
>> I'm not sure it's overstating. Thinking of all the libraries and languag=
es I have ever used, all of them have had a way to create an empty "sequenc=
e" (in whatever way that language represents a sequence, whether it be an a=
rray, container or pair of positions), and in all those languages, operatin=
g on that empty sequence (for example sorting it) is well-defined.
>>=20
>> I could, if you like, produce a concrete list of all the languages and l=
ibraries were sorting or iterating over an empty "sequence" is well-defined=
.. I can't think of any of the top of my head where it is not.
>=20
> I read it as (paraphrased): Virtually every API that takes an array as a =
parameter will accept an empty array. (Array, or other contiguous allocatio=
n of objects)
>=20
> I think of an API "accept"ing this as:
>=20
> - It would not be an error to pass an empty array.
> - It would continue without visible acknowledgement of an error (e.g. no=
throw, no assert, no log).
> - Passing an empty array would also not result in UB.
> - That the results or side effects of passing empty is well defined wher=
e ambiguous: "median(arr[]) will return -11 if you pass an empty array. it =
will not reset the counter thingie".
> - In C family languages, Null is quite commonly used for an empty array =
parameter.
>=20
> I would generally agree with that assessment. Though if #4 were to happen=
, that would almost certainly be a standard library issue. Functions should=
not behave ambiguously in the presence of valid parameters. And if those p=
arameters were invalid, they would have been listed as preconditions, thus =
triggering #3: undefined behavior.
>=20
> And I'm not sure what the last point is getting at. Sure, a NULL pointer =
is often used as the begin or end iterators of a range. But in those cases,=
both the beginning and end pointers will be NULL, so the size will be zero=
.. Or there will be an explicit size parameter, which will be zero. So I don=
't know where you're going with that.
Ok. Thanks for confirming/clarifying. As far as the 5th point (NULL), the p=
oint I was trying to make is that within that context it would make more se=
nse to include APIs which use pointers than to exclude them -- simply becau=
se they are still used often. And when passing array via pointer, NULL can =
represent "empty". Therefore, I concluded that NULL was inclusive. Dependin=
g on the APIs you're using, that representation of 'empty' (NULL) may not b=
e acceptable. And yes, it's fine to object if that NULL pointer disagrees w=
ith a parameter it is paired with (e.g. n or len) -- So foo(nullptr, 2) whe=
re the 2 represents length of the first parameter would be excluded because=
the parameters conflict.
> So the inverse would be: Virtually no APIs reject or object to empty arra=
ys.
>=20
> So I called "Overstatement" - You think Nicol meant something different?
>=20
> If it is true that "Virtually no APIs reject or object to empty arrays" i=
s an overstatement, then there would have to be some non-trivial number of =
standard library APIs that do one of the following:
>=20
> 1. Error when given an empty array.
> 2. Visibly acknowledge an empty array, such as by asserting, logging, or =
throwing an exception.
> 3. Exhibit undefined behavior on an empty array, as specified by the stan=
dard (or has ambiguous behavior, likely a standard library issue).
>=20
> I don't know of any standard library functions that accept ranges for whi=
ch any of these is true. I know of functions that might trigger your #5 NUL=
L condition, but those are almost always "output iterators" of some kind, w=
hich are not really ranges or sequences of values; they're a place to write=
data. And many of them are unbounded (ie: it doesn't take a specific size,=
just a pointer to write stuff to).
Iterators represent empty well.
> And since I said "Virtually", you need to find more than one or two count=
erexamples.
Libraries use differing conventions. Within the standard library, strings A=
PIs stand out to me as NULL intolerant:
char* p(nullptr);
std::string s(p); // bang
s.append(p); // bang
s =3D p; // bang
s +=3D p; // bang
s.assign(p); // bang
s.find(p); // bang
and the cstring interfaces as well. So that's how NULL is perhaps a debatab=
le representation of empty, but I chose those examples because it was easy =
to whip out a bunch of counterexamples (just using libc++ and assuming it c=
onforms).
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_4F0FE641-1E04-43F5-8310-1B6C62478A93
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Diso-8859-1"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mo=
de: space; -webkit-line-break: after-white-space; "><br><div><div>On Jun 16=
, 2013, at 3:26 PM, Nicol Bolas <<a href=3D"mailto:jmckesson@gmail.com">=
jmckesson@gmail.com</a>> wrote:</div><br class=3D"Apple-interchange-newl=
ine"><blockquote type=3D"cite">On Sunday, June 16, 2013 11:58:32 AM UTC-7, =
justin carlson wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div styl=
e=3D"word-wrap:break-word"><div><div>On Jun 16, 2013, at 6:00 AM, Chris Jef=
ferson <<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=
=3D"1Ioc0EtCGVcJ">ch...@bubblescope.net</a>> wrote:</div><blockquote typ=
e=3D"cite">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>On 16/06/13 10:45, justin carlson
wrote:<br>
</div>
<blockquote type=3D"cite">
<div><font face=3D"helvetica"><span style=3D"font-size:13px"></span><=
/font>
<blockquote type=3D"cite">The entire rest of the world disagrees
with you.</blockquote>
<div><br>
</div>
<div>echo "Let's not overstate"</div>
<div><br>
</div>
<br>
<blockquote type=3D"cite">Virtually every API that takes a
sequence of contiguously allocated objects will accept an
empty sequence thereof, regardless of how that API might
define an empty sequence.<br>
</blockquote>
<div><br>
</div>
<div>This is also an overstatement. I explained why this is
often an error, as well as reminded you that you would still
have all the mechanisms you have today to express the
intention where an input may be effectively null or empty.
Where an author specifies a parameter is a sequence and a
sequence is forbidden from being empty that states a contract
very clearly.</div>
<br>
</div>
</blockquote>
<br>
I'm not sure it's overstating. Thinking of all the libraries and
languages I have ever used, all of them have had a way to create an
empty "sequence" (in whatever way that language represents a
sequence, whether it be an array, container or pair of positions),
and in all those languages, operating on that empty sequence (for
example sorting it) is well-defined.<br>
<br>
I could, if you like, produce a concrete list of all the languages
and libraries were sorting or iterating over an empty "sequence" is
well-defined. I can't think of any of the top of my head where it is
not.<br></div></blockquote><div><br></div></div>I read it as (paraphras=
ed): Virtually every API that takes an array as a parameter will accept an =
empty array. (Array, or other contiguous allocation of objects)<div><b=
r></div><div>I think of an API "accept"ing this as:</div><div><br></div><di=
v><span style=3D"white-space:pre"> </span>- It would not be an error to pas=
s an empty array.</div><div><span style=3D"white-space:pre"> </span>- =
It would continue without visible acknowledgement of an error (e.g. no thro=
w, no assert, no log).</div><div><span style=3D"white-space:pre"> </span>- =
Passing an empty array would also not result in UB.</div><div><span style=
=3D"white-space:pre"> </span>- That the results or side effects of passing =
empty is well defined where ambiguous: "median(arr[]) will return -11 if yo=
u pass an empty array. it will not reset the counter thingie".</div><div><s=
pan style=3D"white-space:pre"> </span>- In C family languages, Null is quit=
e commonly used for an empty array parameter.<br></div></div></blockquote><=
div><br>I would generally agree with that assessment. Though if #4 were to =
happen, that would almost certainly be a standard library issue. Functions =
should not behave ambiguously in the presence of valid parameters. And if t=
hose parameters were invalid, they would have been listed as preconditions,=
thus triggering #3: undefined behavior.<br><br>And I'm not sure what the l=
ast point is getting at. Sure, a NULL pointer is often used as the begin or=
end iterators of a range. But in those cases, both the beginning and end p=
ointers will be NULL, so the size will be zero. Or there will be an explici=
t size parameter, which will be zero. So I don't know where you're going wi=
th that.<br></div></blockquote><div><br></div><div>Ok. Thanks for confirmin=
g/clarifying. As far as the 5th point (NULL), the point I was trying to mak=
e is that within that context it would make more sense to include APIs whic=
h use pointers than to exclude them -- simply because they are still used o=
ften. And when passing array via pointer, NULL can represent "empty". There=
fore, I concluded that NULL was inclusive. Depending on the APIs you're usi=
ng, that representation of 'empty' (NULL) may not be acceptable. And yes, i=
t's fine to object if that NULL pointer disagrees with a parameter it is pa=
ired with (e.g. n or len) -- So foo(nullptr, 2) where the 2 represents leng=
th of the first parameter would be excluded because the parameters conflict=
..</div><div><br></div><br><blockquote type=3D"cite"><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div></div><=
/div><div>So the inverse would be: Virtually no APIs reject or object to em=
pty arrays.</div><div><br></div><div>So I called "Overstatement" - You=
think Nicol meant something different?</div></div></blockquote><div><br>If=
it is true that "Virtually no APIs reject or object to empty arrays" is an=
overstatement, then there would have to be some non-trivial number of stan=
dard library APIs that do one of the following:<br><br>1. Error when given =
an empty array.<br>2. Visibly acknowledge an empty array, such as by assert=
ing, logging, or throwing an exception.<br>3. Exhibit undefined behavior on=
an empty array, as specified by the standard (or has ambiguous behavior, l=
ikely a standard library issue).<br><br>I don't know of any standard librar=
y functions that accept ranges for which any of these is true. I know of fu=
nctions that might trigger your #5 NULL condition, but those are almost alw=
ays "output iterators" of some kind, which are not really ranges or sequenc=
es of values; they're a place to write data. And many of them are unbounded=
(ie: it doesn't take a specific size, just a pointer to write stuff to).<b=
r></div></blockquote><div><br></div><div>Iterators represent empty well.</d=
iv><br><blockquote type=3D"cite"><div>And since I said "Virtually", you nee=
d to find more than one or two counterexamples.<br></div></blockquote><div>=
<br></div><div>Libraries use differing conventions. Within the standard lib=
rary, strings APIs stand out to me as NULL intolerant:</div><div><br></div>=
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>char*=
p(nullptr);</div><div><span class=3D"Apple-tab-span" style=3D"white-space:=
pre"> </span>std::string s(p); // bang</div><div><span class=3D"Apple-=
tab-span" style=3D"white-space:pre"> </span>s.append(p); // bang<=
/div><div><span class=3D"Apple-tab-span" style=3D"white-space: pre; "> </sp=
an>s =3D p; // bang</div><div><span class=3D"Apple-tab-span" style=3D"white=
-space: pre; "> </span>s +=3D p; // bang</div><div><span class=3D"Apple-tab=
-span" style=3D"white-space:pre"> </span>s.assign(p); // bang</div><div><sp=
an class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>s.find(p); //=
bang</div><div><br></div><div>and the cstring interfaces as well. So that'=
s how NULL is perhaps a debatable representation of empty, but I chose thos=
e examples because it was easy to whip out a bunch of counterexamples (just=
using libc++ and assuming it conforms).</div><div><br></div></div></body><=
/html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--Apple-Mail=_4F0FE641-1E04-43F5-8310-1B6C62478A93--
.
Author: Chris Jefferson <chris@bubblescope.net>
Date: Sun, 16 Jun 2013 22:51:08 +0100
Raw View
This is a multi-part message in MIME format.
--------------000006080403000602010809
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
On 16/06/13 22:34, justin carlson wrote:
>
> On Jun 16, 2013, at 3:26 PM, Nicol Bolas <jmckesson@gmail.com
> <mailto:jmckesson@gmail.com>> wrote:
>
>> On Sunday, June 16, 2013 11:58:32 AM UTC-7, justin carlson wrote:
>>
>> On Jun 16, 2013, at 6:00 AM, Chris Jefferson
>> <ch...@bubblescope.net <javascript:>> wrote:
>>> On 16/06/13 10:45, justin carlson wrote:
>>>>> The entire rest of the world disagrees with you.
>>>>
>>>> echo "Let's not overstate"
>>>>
>>>>
>>>>> Virtually every API that takes a sequence of contiguously
>>>>> allocated objects will accept an empty sequence thereof,
>>>>> regardless of how that API might define an empty sequence.
>>>>
>>>> This is also an overstatement. I explained why this is often an
>>>> error, as well as reminded you that you would still have all
>>>> the mechanisms you have today to express the intention where an
>>>> input may be effectively null or empty. Where an author
>>>> specifies a parameter is a sequence and a sequence is forbidden
>>>> from being empty that states a contract very clearly.
>>>>
>>>
>>> I'm not sure it's overstating. Thinking of all the libraries and
>>> languages I have ever used, all of them have had a way to create
>>> an empty "sequence" (in whatever way that language represents a
>>> sequence, whether it be an array, container or pair of
>>> positions), and in all those languages, operating on that empty
>>> sequence (for example sorting it) is well-defined.
>>>
>>> I could, if you like, produce a concrete list of all the
>>> languages and libraries were sorting or iterating over an empty
>>> "sequence" is well-defined. I can't think of any of the top of
>>> my head where it is not.
>>
>> I read it as (paraphrased): Virtually every API that takes an
>> array as a parameter will accept an empty array. (Array, or other
>> contiguous allocation of objects)
>>
>> I think of an API "accept"ing this as:
>>
>> - It would not be an error to pass an empty array.
>> - It would continue without visible acknowledgement of an error
>> (e.g. no throw, no assert, no log).
>> - Passing an empty array would also not result in UB.
>> - That the results or side effects of passing empty is well
>> defined where ambiguous: "median(arr[]) will return -11 if you
>> pass an empty array. it will not reset the counter thingie".
>> - In C family languages, Null is quite commonly used for an empty
>> array parameter.
>>
>>
>> I would generally agree with that assessment. Though if #4 were to
>> happen, that would almost certainly be a standard library issue.
>> Functions should not behave ambiguously in the presence of valid
>> parameters. And if those parameters were invalid, they would have
>> been listed as preconditions, thus triggering #3: undefined behavior.
>>
>> And I'm not sure what the last point is getting at. Sure, a NULL
>> pointer is often used as the begin or end iterators of a range. But
>> in those cases, both the beginning and end pointers will be NULL, so
>> the size will be zero. Or there will be an explicit size parameter,
>> which will be zero. So I don't know where you're going with that.
>
> Ok. Thanks for confirming/clarifying. As far as the 5th point (NULL),
> the point I was trying to make is that within that context it would
> make more sense to include APIs which use pointers than to exclude
> them -- simply because they are still used often. And when passing
> array via pointer, NULL can represent "empty". Therefore, I concluded
> that NULL was inclusive. Depending on the APIs you're using, that
> representation of 'empty' (NULL) may not be acceptable. And yes, it's
> fine to object if that NULL pointer disagrees with a parameter it is
> paired with (e.g. n or len) -- So foo(nullptr, 2) where the 2
> represents length of the first parameter would be excluded because the
> parameters conflict.
>
>
>> So the inverse would be: Virtually no APIs reject or object to
>> empty arrays.
>>
>> So I called "Overstatement" - You think Nicol meant something
>> different?
>>
>>
>> If it is true that "Virtually no APIs reject or object to empty
>> arrays" is an overstatement, then there would have to be some
>> non-trivial number of standard library APIs that do one of the following:
>>
>> 1. Error when given an empty array.
>> 2. Visibly acknowledge an empty array, such as by asserting, logging,
>> or throwing an exception.
>> 3. Exhibit undefined behavior on an empty array, as specified by the
>> standard (or has ambiguous behavior, likely a standard library issue).
>>
>> I don't know of any standard library functions that accept ranges for
>> which any of these is true. I know of functions that might trigger
>> your #5 NULL condition, but those are almost always "output
>> iterators" of some kind, which are not really ranges or sequences of
>> values; they're a place to write data. And many of them are unbounded
>> (ie: it doesn't take a specific size, just a pointer to write stuff to).
>
> Iterators represent empty well.
>
>> And since I said "Virtually", you need to find more than one or two
>> counterexamples.
>
> Libraries use differing conventions. Within the standard library,
> strings APIs stand out to me as NULL intolerant:
>
> char* p(nullptr);
> std::string s(p); // bang
> s.append(p); // bang
> s = p; // bang
> s += p; // bang
> s.assign(p); // bang
> s.find(p); // bang
No, that's not (to me) an empty range. An empty C string range would be:
char c[] = {'\0'}. That works fine in all the cases you give about. I
don't know anything which wouldn't work perfectly with a non-NULL empty
C string.
Chris
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--------------000006080403000602010809
Content-Type: text/html; charset=ISO-8859-1
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">On 16/06/13 22:34, justin carlson
wrote:<br>
</div>
<blockquote
cite="mid:22A59EE7-1E1C-42F1-B166-040D7CA8A634@yahoo.co.uk"
type="cite">
<meta http-equiv="Content-Type" content="text/html;
charset=ISO-8859-1">
<br>
<div>
<div>On Jun 16, 2013, at 3:26 PM, Nicol Bolas <<a
moz-do-not-send="true" href="mailto:jmckesson@gmail.com">jmckesson@gmail.com</a>>
wrote:</div>
<br class="Apple-interchange-newline">
<blockquote type="cite">On Sunday, June 16, 2013 11:58:32 AM
UTC-7, justin carlson wrote:
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style="word-wrap:break-word">
<div>
<div>On Jun 16, 2013, at 6:00 AM, Chris Jefferson <<a
moz-do-not-send="true" href="javascript:"
target="_blank" gdf-obfuscated-mailto="1Ioc0EtCGVcJ">ch...@bubblescope.net</a>>
wrote:</div>
<blockquote type="cite">
<div bgcolor="#FFFFFF" text="#000000">
<div>On 16/06/13 10:45, justin carlson wrote:<br>
</div>
<blockquote type="cite">
<div><font face="helvetica"><span
style="font-size:13px"></span></font>
<blockquote type="cite">The entire rest of the
world disagrees with you.</blockquote>
<div><br>
</div>
<div>echo "Let's not overstate"</div>
<div><br>
</div>
<br>
<blockquote type="cite">Virtually every API that
takes a sequence of contiguously allocated
objects will accept an empty sequence thereof,
regardless of how that API might define an
empty sequence.<br>
</blockquote>
<div><br>
</div>
<div>This is also an overstatement. I explained
why this is often an error, as well as
reminded you that you would still have all the
mechanisms you have today to express the
intention where an input may be effectively
null or empty. Where an author specifies a
parameter is a sequence and a sequence is
forbidden from being empty that states a
contract very clearly.</div>
<br>
</div>
</blockquote>
<br>
I'm not sure it's overstating. Thinking of all the
libraries and languages I have ever used, all of
them have had a way to create an empty "sequence"
(in whatever way that language represents a
sequence, whether it be an array, container or pair
of positions), and in all those languages, operating
on that empty sequence (for example sorting it) is
well-defined.<br>
<br>
I could, if you like, produce a concrete list of all
the languages and libraries were sorting or
iterating over an empty "sequence" is well-defined.
I can't think of any of the top of my head where it
is not.<br>
</div>
</blockquote>
<div><br>
</div>
</div>
I read it as (paraphrased): Virtually every API that takes
an array as a parameter will accept an empty array.
(Array, or other contiguous allocation of objects)
<div><br>
</div>
<div>I think of an API "accept"ing this as:</div>
<div><br>
</div>
<div><span style="white-space:pre"> </span>- It would not
be an error to pass an empty array.</div>
<div><span style="white-space:pre"> </span>- It would
continue without visible acknowledgement of an error
(e.g. no throw, no assert, no log).</div>
<div><span style="white-space:pre"> </span>- Passing an
empty array would also not result in UB.</div>
<div><span style="white-space:pre"> </span>- That the
results or side effects of passing empty is well defined
where ambiguous: "median(arr[]) will return -11 if you
pass an empty array. it will not reset the counter
thingie".</div>
<div><span style="white-space:pre"> </span>- In C family
languages, Null is quite commonly used for an empty
array parameter.<br>
</div>
</div>
</blockquote>
<div><br>
I would generally agree with that assessment. Though if #4
were to happen, that would almost certainly be a standard
library issue. Functions should not behave ambiguously in
the presence of valid parameters. And if those parameters
were invalid, they would have been listed as preconditions,
thus triggering #3: undefined behavior.<br>
<br>
And I'm not sure what the last point is getting at. Sure, a
NULL pointer is often used as the begin or end iterators of
a range. But in those cases, both the beginning and end
pointers will be NULL, so the size will be zero. Or there
will be an explicit size parameter, which will be zero. So I
don't know where you're going with that.<br>
</div>
</blockquote>
<div><br>
</div>
<div>Ok. Thanks for confirming/clarifying. As far as the 5th
point (NULL), the point I was trying to make is that within
that context it would make more sense to include APIs which
use pointers than to exclude them -- simply because they are
still used often. And when passing array via pointer, NULL can
represent "empty". Therefore, I concluded that NULL was
inclusive. Depending on the APIs you're using, that
representation of 'empty' (NULL) may not be acceptable. And
yes, it's fine to object if that NULL pointer disagrees with a
parameter it is paired with (e.g. n or len) -- So foo(nullptr,
2) where the 2 represents length of the first parameter would
be excluded because the parameters conflict.</div>
<div><br>
</div>
<br>
<blockquote type="cite">
<blockquote class="gmail_quote" style="margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style="word-wrap:break-word">
<div>So the inverse would be: Virtually no APIs reject or
object to empty arrays.</div>
<div><br>
</div>
<div>So I called "Overstatement" - You think Nicol meant
something different?</div>
</div>
</blockquote>
<div><br>
If it is true that "Virtually no APIs reject or object to
empty arrays" is an overstatement, then there would have to
be some non-trivial number of standard library APIs that do
one of the following:<br>
<br>
1. Error when given an empty array.<br>
2. Visibly acknowledge an empty array, such as by asserting,
logging, or throwing an exception.<br>
3. Exhibit undefined behavior on an empty array, as
specified by the standard (or has ambiguous behavior, likely
a standard library issue).<br>
<br>
I don't know of any standard library functions that accept
ranges for which any of these is true. I know of functions
that might trigger your #5 NULL condition, but those are
almost always "output iterators" of some kind, which are not
really ranges or sequences of values; they're a place to
write data. And many of them are unbounded (ie: it doesn't
take a specific size, just a pointer to write stuff to).<br>
</div>
</blockquote>
<div><br>
</div>
<div>Iterators represent empty well.</div>
<br>
<blockquote type="cite">
<div>And since I said "Virtually", you need to find more than
one or two counterexamples.<br>
</div>
</blockquote>
<div><br>
</div>
<div>Libraries use differing conventions. Within the standard
library, strings APIs stand out to me as NULL intolerant:</div>
<div><br>
</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>char*
p(nullptr);</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>std::string
s(p); // bang</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>s.append(p); // bang</div>
<div><span class="Apple-tab-span" style="white-space: pre; "> </span>s
= p; // bang</div>
<div><span class="Apple-tab-span" style="white-space: pre; "> </span>s
+= p; // bang</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>s.assign(p);
// bang</div>
<div><span class="Apple-tab-span" style="white-space:pre"> </span>s.find(p);
// bang</div>
</div>
</blockquote>
<br>
No, that's not (to me) an empty range. An empty C string range would
be: char c[] = {'\0'}. That works fine in all the cases you give
about. I don't know anything which wouldn't work perfectly with a
non-NULL empty C string.<br>
<br>
Chris<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
<br />
<br />
--------------000006080403000602010809--
.
Author: Olaf van der Spek <olafvdspek@gmail.com>
Date: Mon, 17 Jun 2013 01:15:17 +0200
Raw View
On Sun, Jun 16, 2013 at 10:33 PM, justin carlson
<carrierandoperator@yahoo.co.uk> wrote:
> Hmkay - Suppose we were to use the boost iterator_range, or the std::range in its current form. What would the following look like using those implementations?
Something like this?
namespace MyAPI {
void fill(std::range<double*sq); // << extern
}
void foo() {
double a[5];
MyAPI::fill(a);
std::array<double, 5>b;
MyAPI::fill(b);
std::vector<double>c(5);
MyAPI::fill(c);
MyAPI::fill(std::range<double*>(c.begin(), c.end())); // note:
iterator pair ctor is a 'maybe'
MyAPI::fill(std::range<double*>(c.data(), c.size()));
}
void MyAPI::fill(std::range<double*sq) {
for (double& at:sq) at = 7; // set all elements to 7
}
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Mon, 17 Jun 2013 03:37:57 -0400
Raw View
Ok. I tried that on one proposed implementation out there. The second to th=
e last failed because std::vector<double>::iterator is not a pointer (on my=
system). That was pretty easy to fix -- required another variable and line=
.. The last failed because there is not a range<T>(ptr,n) constructor (It's =
implemented using iterators). That implementation was quite simple (not a b=
ad thing). IDK if it's what everybody regards as "the" proposal.
On Jun 16, 2013, at 7:15 PM, Olaf van der Spek <olafvdspek@gmail.com> wrote=
:
> On Sun, Jun 16, 2013 at 10:33 PM, justin carlson
> <carrierandoperator@yahoo.co.uk> wrote:
>> Hmkay - Suppose we were to use the boost iterator_range, or the std::ran=
ge in its current form. What would the following look like using those impl=
ementations?
>=20
> Something like this?
>=20
>=20
> namespace MyAPI {
> void fill(std::range<double*sq); // << extern
> }
>=20
> void foo() {
> double a[5];
> MyAPI::fill(a);
> std::array<double, 5>b;
> MyAPI::fill(b);
> std::vector<double>c(5);
> MyAPI::fill(c);
> MyAPI::fill(std::range<double*>(c.begin(), c.end())); // note:
> iterator pair ctor is a 'maybe'
> MyAPI::fill(std::range<double*>(c.data(), c.size()));
> }
>=20
> void MyAPI::fill(std::range<double*sq) {
> for (double& at:sq) at =3D 7; // set all elements to 7
> }
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Mon, 17 Jun 2013 04:04:53 -0400
Raw View
On Jun 16, 2013, at 5:51 PM, Chris Jefferson <chris@bubblescope.net> wrote:
>> Libraries use differing conventions. Within the standard library, strings APIs stand out to me as NULL intolerant:
>>
>> char* p(nullptr);
>> std::string s(p); // bang
>> s.append(p); // bang
>> s = p; // bang
>> s += p; // bang
>> s.assign(p); // bang
>> s.find(p); // bang
>
> No, that's not (to me) an empty range. An empty C string range would be: char c[] = {'\0'}. That works fine in all the cases you give about. I don't know anything which wouldn't work perfectly with a non-NULL empty C string.
So if one were to follow that prescription, then
int i(0);
sequence(&i,0); // OK
sequence(nullptr,0); // INVALID
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: stackmachine@hotmail.com
Date: Mon, 17 Jun 2013 01:41:50 -0700 (PDT)
Raw View
------=_Part_11_19063342.1371458510710
Content-Type: text/plain; charset=ISO-8859-1
I haven't read the whole thread since the discussion is be pointless. You
seem to confuse two different things: a null reference and an empty range.
An empty range refers to a valid range whose size is 0. A null reference
does not refer to a valid range (and therefore has no size).
I agree that "null"-sequences are questionable, but empty sequences are
definitely desirable to have. Think of algorithms that do not modify the
underlying sequence, but return a new sequence, like taking a subrange or
splitting on the occurence of a specific element. I found those to be very
useful and it is perfectly valid to return an empty sequence for these
kinds of algorithms.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_11_19063342.1371458510710
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
I haven't read the whole thread since the discussion is be pointless.=
You seem to confuse two different things: a null reference and an empty ra=
nge.<br>An empty range refers to a valid range whose size is 0. A null refe=
rence does not refer to a valid range (and therefore has no size).<br>I agr=
ee that "null"-sequences are questionable, but empty sequences are definite=
ly desirable to have. Think of algorithms that do not modify the underlying=
sequence, but return a new sequence, like taking a subrange or splitting o=
n the occurence of a specific element. I found those to be very useful and =
it is perfectly valid to return an empty sequence for these kinds of algori=
thms.<br>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_11_19063342.1371458510710--
.
Author: Alex B <devalexb@gmail.com>
Date: Mon, 17 Jun 2013 09:53:18 -0400
Raw View
--089e0160b4323e5c0004df59eb47
Content-Type: text/plain; charset=ISO-8859-1
On Mon, Jun 17, 2013 at 4:41 AM, <stackmachine@hotmail.com> wrote:
> You seem to confuse two different things: a null reference and an empty
> range.
Exactly.
You (the OP) talk a lot about "reference semantics". The problem I think is
that you are seeing this as a reference to the *contained data* instead of
a reference to the *container/range* itself. If an empty vector is a
perfectly valid and existing object, I don't see why a reference to it
would be invalid.
vector<int> v; // empty vector
vector<int>& v_ref = v; // valid reference even if vector is empty
sequence<int> v_seq = v; // this *has* to be valid as well
v_seq.front() = ...; // *this* is invalid...
v.front() = ...; // ... but as much as this
You talked a lot about empty containers/ranges/sequences that you consider
invalid and should never be passed to a function as a parameter. This point
of view can be perfectly valid *in your own coding standards* (I could
imagine a software company having this as an internal coding policy). I
understand why this could work as a "philosophy", but we are talking about
standardizing here. What you suggest goes way beyond your proposal; why
should this particular class in the standard (if it ever becomes part of
it) follow a different (but still valid) philosophy than the rest of the
standard? I'm not saying that your paradigm is invalid, but you are
challenging the whole standard with your proposal (which *should* be a
rather simple one). For this reason, you should try to refocus your
proposal on the problems it is trying to solve and what it is offering (you
already summed them up quite nicely) rather than adding this kind of
artificial limitation made to satisfy one particular coding policy which
cannot be seen anywhere in the standard.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0160b4323e5c0004df59eb47
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Mon, Jun 17, 2013 at 4:41 AM, <span dir=3D"ltr"><<a=
href=3D"mailto:stackmachine@hotmail.com" target=3D"_blank">stackmachine@ho=
tmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><div class=3D=
"gmail_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex">=A0You seem to confuse two different things: a null refere=
nce and an empty range.</blockquote>
<div><br></div><div style>Exactly.</div><div style><br></div><div style>You=
(the OP) talk a lot about "reference semantics". The problem I t=
hink is that you are seeing this as a reference to the <b>contained data</b=
> instead of a reference to the <b>container/range</b>=A0itself. If an empt=
y vector is a perfectly valid and existing object, I don't see why a re=
ference to it would be invalid.</div>
<div style><br></div><div style>vector<int> v; // empty vector</div><=
div style>vector<int>& v_ref =3D v; // valid reference even if ve=
ctor is empty</div><div style>sequence<int> v_seq =3D v; // this <b>h=
as</b>=A0to be valid as well</div>
<div style>v_seq.front() =3D ...; // <b>this</b> is invalid...<br></div><di=
v style>v.front() =3D ...; // ... but as much as this</div><div style><br><=
/div><div style>You talked a lot about empty containers/ranges/sequences th=
at you consider invalid and should never be passed to a function as a param=
eter. This point of view can be perfectly valid <i>in your own coding stand=
ards</i>=A0(I could imagine a software company having this as an internal c=
oding policy). I understand why this could work as a "philosophy"=
, but we are talking about standardizing here. What you suggest goes way be=
yond your proposal; why should this particular class in the standard (if it=
ever becomes part of it) follow a different (but still valid) philosophy t=
han the rest of the standard? I'm not saying that your paradigm is inva=
lid, but you are challenging the whole standard with your proposal (which <=
i>should</i>=A0be a rather simple one). For this reason, you should try to =
refocus your proposal on the problems it is trying to solve and what it is =
offering (you already summed them up quite nicely) rather than adding this =
kind of artificial limitation made to satisfy one particular coding policy =
which cannot be seen anywhere in the standard.</div>
</div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--089e0160b4323e5c0004df59eb47--
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Mon, 17 Jun 2013 13:52:40 -0400
Raw View
--Apple-Mail=_CFE4705A-755B-4E6B-9142-72AD9B07FF7E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1
On Jun 17, 2013, at 9:53 AM, Alex B <devalexb@gmail.com> wrote:
> On Mon, Jun 17, 2013 at 4:41 AM, <stackmachine@hotmail.com> wrote:
> You seem to confuse two different things: a null reference and an empty =
range.
>=20
> Exactly.
>=20
> You (the OP) talk a lot about "reference semantics". The problem I think =
is that you are seeing this as a reference to the contained data instead of=
a reference to the container/range itself. If an empty vector is a perfect=
ly valid and existing object, I don't see why a reference to it would be in=
valid.
>=20
> vector<int> v; // empty vector
> vector<int>& v_ref =3D v; // valid reference even if vector is empty
> sequence<int> v_seq =3D v; // this has to be valid as well
> v_seq.front() =3D ...; // this is invalid...
> v.front() =3D ...; // ... but as much as this
As a reference does not represent absence by design:
void foo(const T&);
neither does a sequence:
void foo(sequence<T>);
That's a better way to think of it (i.e. not a range which may be empty). S=
o the problem I was trying to solve when implementing sequences was "Refere=
nces are great - How can I express that for arrays?".
> You talked a lot about empty containers/ranges/sequences that you conside=
r invalid and should never be passed to a function as a parameter. This poi=
nt of view can be perfectly valid in your own coding standards (I could ima=
gine a software company having this as an internal coding policy). I unders=
tand why this could work as a "philosophy", but we are talking about standa=
rdizing here. What you suggest goes way beyond your proposal; why should th=
is particular class in the standard (if it ever becomes part of it) follow =
a different (but still valid) philosophy than the rest of the standard?
Because I'm not about to propose a change to the language (which references=
obviously were).
> I'm not saying that your paradigm is invalid, but you are challenging the=
whole standard with your proposal (which should be a rather simple one).
"Challenging the whole standard" is an overstatement. However, it's fine to=
say sequences are dissimilar from _iterators_ because sequences forbid emp=
ty state.
> For this reason, you should try to refocus your proposal on the problems =
it is trying to solve and what it is offering (you already summed them up q=
uite nicely) rather than adding this kind of artificial limitation made to =
satisfy one particular coding policy which cannot be seen anywhere in the s=
tandard.
I've expressed sympathy for the ability to represent empty state and said t=
here would be an option to enable this behavior in a draft implementation. =
I've also stated I can be persuaded that empty should be permitted. Thanks =
for weighing in.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_CFE4705A-755B-4E6B-9142-72AD9B07FF7E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Diso-8859-1"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mo=
de: space; -webkit-line-break: after-white-space; "><br><div><div>On Jun 17=
, 2013, at 9:53 AM, Alex B <<a href=3D"mailto:devalexb@gmail.com">devale=
xb@gmail.com</a>> wrote:</div><br class=3D"Apple-interchange-newline"><b=
lockquote type=3D"cite"><div dir=3D"ltr">On Mon, Jun 17, 2013 at 4:41 AM, =
<span dir=3D"ltr"><<a href=3D"mailto:stackmachine@hotmail.com" target=3D=
"_blank">stackmachine@hotmail.com</a>></span> wrote:<br><div class=3D"gm=
ail_extra"><div class=3D"gmail_quote">
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p=
adding-left:1ex"> You seem to confuse two different things: a null ref=
erence and an empty range.</blockquote>
<div><br></div><div style=3D"">Exactly.</div><div style=3D""><br></div><div=
style=3D"">You (the OP) talk a lot about "reference semantics". The proble=
m I think is that you are seeing this as a reference to the <b>contained da=
ta</b> instead of a reference to the <b>container/range</b> itself. If=
an empty vector is a perfectly valid and existing object, I don't see why =
a reference to it would be invalid.</div>
<div style=3D""><br></div><div style=3D"">vector<int> v; // empty vec=
tor</div><div style=3D"">vector<int>& v_ref =3D v; // valid refer=
ence even if vector is empty</div><div style=3D"">sequence<int> v_seq=
=3D v; // this <b>has</b> to be valid as well</div>
<div style=3D"">v_seq.front() =3D ...; // <b>this</b> is invalid...<br></di=
v><div style=3D"">v.front() =3D ...; // ... but as much as this</div></div>=
</div></div></blockquote><div><br></div><div><div>As a reference does not r=
epresent absence by design:</div><div> void foo(const T&);</div><d=
iv><br></div><div>neither does a sequence:</div><div> void foo(sequenc=
e<T>);</div><div><br></div><div>That's a better way to think of it (i=
..e. not a range which may be empty). So the problem I was trying to solve w=
hen implementing sequences was "References are great - How can I express th=
at for arrays?".</div><div><br></div></div><div style=3D"margin: 0px; paddi=
ng: 0px; border: 0px; vertical-align: baseline; color: rgb(34, 34, 34); fon=
t-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: =
rgb(255, 255, 255); position: static; z-index: auto; "><div><br></div></div=
><blockquote type=3D"cite"><div dir=3D"ltr"><div class=3D"gmail_extra"><div=
class=3D"gmail_quote"><div style=3D"">You talked a lot about empty contain=
ers/ranges/sequences that you consider invalid and should never be passed t=
o a function as a parameter. This point of view can be perfectly valid <i>i=
n your own coding standards</i> (I could imagine a software company ha=
ving this as an internal coding policy). I understand why this could work a=
s a "philosophy", but we are talking about standardizing here. What you sug=
gest goes way beyond your proposal; why should this particular class in the=
standard (if it ever becomes part of it) follow a different (but still val=
id) philosophy than the rest of the standard?</div></div></div></div></bloc=
kquote><div><br></div><div>Because I'm not about to propose a change to the=
language (which references obviously were).</div><br><blockquote type=3D"c=
ite"><div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"=
><div style=3D"">I'm not saying that your paradigm is invalid, but you are =
challenging the whole standard with your proposal (which <i>should</i> =
;be a rather simple one).</div></div></div></div></blockquote><div><br></di=
v><div>"Challenging the whole standard" is an overstatement. However, it's =
fine to say sequences are dissimilar from _iterators_ because sequences for=
bid empty state.</div><br><blockquote type=3D"cite"><div dir=3D"ltr"><div c=
lass=3D"gmail_extra"><div class=3D"gmail_quote"><div style=3D"">For this re=
ason, you should try to refocus your proposal on the problems it is trying =
to solve and what it is offering (you already summed them up quite nicely) =
rather than adding this kind of artificial limitation made to satisfy one p=
articular coding policy which cannot be seen anywhere in the standard.</div=
></div></div></div></blockquote><br></div><div><div style=3D"margin: 0px; p=
adding: 0px; border: 0px; vertical-align: baseline; color: rgb(34, 34, 34);=
font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-col=
or: rgb(255, 255, 255); ">I've expressed sympathy for the ability to repres=
ent empty state and said there would be an option to enable this behavior i=
n a draft implementation. I've also stated I can be persuaded that empty sh=
ould be permitted. Thanks for weighing in.</div><div style=3D"margin: 0px; =
padding: 0px; border: 0px; vertical-align: baseline; color: rgb(34, 34, 34)=
; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-co=
lor: rgb(255, 255, 255); "><br></div></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--Apple-Mail=_CFE4705A-755B-4E6B-9142-72AD9B07FF7E--
.
Author: Alex B <devalexb@gmail.com>
Date: Mon, 17 Jun 2013 14:42:19 -0400
Raw View
--001a11c34da0e027d304df5df48e
Content-Type: text/plain; charset=ISO-8859-1
> As a reference does not represent absence by design:
> void foo(const T&);
>
> neither does a sequence:
> void foo(sequence<T>);
>
> That's a better way to think of it (i.e. not a range which may be empty).
>
I still don't get it. For me, the purpose of a sequence is to replace this
kind of function:
void foo(const vector<T>&); // *not *"const T&" like in your example
by this:
void foo(sequence<T>);
That is the most obvious use-case I can see; a simple drop-in replacement
in the declaration without any change in the logic/meaning.
But are you suggesting that your use-case is to replace a function taking a
*reference to a single element* (not a container) should take a sequence
instead? Doing so completely changes the meaning of your function so I am a
bit lost.
It would really help to understand what is the intent of your class if you
bring real-world code samples. For example, show an existing (real)
function and a new version that would benefit from sequences.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c34da0e027d304df5df48e
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div style=3D"word-wrap:break-word"><div><di=
v><div>As a reference does not represent absence by design:</div>
<div>=A0void foo(const T&);</div><div><br></div><div>neither does a seq=
uence:</div><div>=A0void foo(sequence<T>);</div><div><br></div><div>T=
hat's a better way to think of it (i.e. not a range which may be empty)=
..</div>
</div></div></div></blockquote><div><br></div><div style>I still don't =
get it. For me, the purpose of a sequence is to replace this kind of functi=
on:</div><div style>=A0 void foo(const vector<T>&); =A0 // <b><u>=
not </u></b>"const T&" like in your example<br>
</div><div style><br></div><div style>by this:</div><div style>=A0 void foo=
(sequence<T>);</div><div style><br></div><div style>That is the most =
obvious use-case I can see; a simple drop-in replacement in the declaration=
without any change in the logic/meaning.</div>
<div style>But are you suggesting that your use-case is to replace a functi=
on taking a <i>reference to a single element</i> (not a container) should t=
ake a sequence instead? Doing so completely changes the meaning of your fun=
ction so I am a bit lost.</div>
<div style><br></div><div style>It would really help to understand what is =
the intent of your class if you bring real-world=A0code samples. For exampl=
e, show an existing (real) function and a new version that would benefit fr=
om sequences.</div>
</div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--001a11c34da0e027d304df5df48e--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Mon, 17 Jun 2013 13:47:39 -0500
Raw View
--20cf306f750c51c35b04df5e0a79
Content-Type: text/plain; charset=ISO-8859-1
On 15 June 2013 21:55, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>
> The entire rest of the world disagrees with you. Virtually every API that
> takes a sequence of contiguously allocated objects will accept an empty
> sequence thereof, regardless of how that API might define an empty sequence.
>
Including *every* API he mentioned:
size_t foo(const int* elements, size_t n);
size_t foo(const std::array<int, N>&);
size_t foo(const std::vector<int>&);
size_t foo(const std::vector<int,SomeSpecialAllocator>&);
template<typename TArbitraryContainer>
size_t foo(const TArbitraryContainer&) {
/* e.g. TArbitraryContainer must support subscripting and size() */
}
Those *all* take ranges that can be zero sized, so his proposal is *not* a
replacement for those interfaces.
Be that as it may, if you wish to persist with this notion that "empty ==
> invalid == error", then you need to be *serious* about it. And that means
> you *need* to throw an exception on any circumstance that would result in
> an empty range. Merely being "undefined behavior" isn't enough, even by
> your own standard:
I disagree. Should he write it up and come to a committee meeting to
present it, it will not change my vote of "strongly against" whether it is
undefined or throws an exception.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--20cf306f750c51c35b04df5e0a79
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 15 June 2013 21:55, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:=
jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span> w=
rote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br><br>The entire rest of the world disagrees with=20
you. Virtually every API that takes a sequence of contiguously allocated ob=
jects will accept an empty sequence thereof, regardless of how that API mig=
ht define an empty sequence.<br></blockquote><div><br>Including *every* API=
he mentioned:<br>
<br><div style=3D"background-color:rgb(250,250,250);border:1px solid rgb(18=
7,187,187);word-wrap:break-word"><code><div><span style=3D"color:#000">size=
_t foo</span><span style=3D"color:#660">(</span><span style=3D"color:#008">=
const</span><span style=3D"color:#000"> </span><span style=3D"color:#008">i=
nt</span><span style=3D"color:#660">*</span><span style=3D"color:#000"> ele=
ments</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> =
size_t n</span><span style=3D"color:#660">);</span><span style=3D"color:#00=
0"><br>
</span><span style=3D"color:#000">size_t foo</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#008">const</span><span style=3D"color:#000=
"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#000"=
>array</span><span style=3D"color:#660"><</span><span style=3D"color:#00=
8">int</span><span style=3D"color:#660">,</span><span style=3D"color:#000">=
N</span><span style=3D"color:#660">>&);</span></div>
<div><span style=3D"color:#000">size_t foo</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#008">const</span><span style=3D"color:#000">=
std</span><span style=3D"color:#660">::</span><span style=3D"color:#000">v=
ector</span><span style=3D"color:#080"><int></span><span style=3D"col=
or:#660">&);</span></div>
<div><span style=3D"color:#000">size_t foo</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#008">const</span><span style=3D"color:#000">=
std</span><span style=3D"color:#660">::</span><span style=3D"color:#000">v=
ector</span><span style=3D"color:#660"><</span><span style=3D"color:#008=
">int</span><span style=3D"color:#660">,</span><span style=3D"color:#606">S=
omeSpecialAllocator</span><span style=3D"color:#660">>&);</span></di=
v>
<div><span style=3D"color:#000"></span><span style=3D"color:#008"><br>templ=
ate</span><span style=3D"color:#660"><</span><span style=3D"color:#008">=
typename</span><span style=3D"color:#000"> </span><span style=3D"color:#606=
">TArbitraryContainer</span><span style=3D"color:#660">></span></div>
<div><span style=3D"color:#000">size_t foo</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#008">const</span><span style=3D"color:#000">=
</span><span style=3D"color:#606">TArbitraryContainer</span><span style=3D=
"color:#660">&)</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">{</span><span style=3D"color:#000"><br>
=A0</span><span style=3D"color:#800">/* e.g. TArbitraryContainer must suppo=
rt subscripting and size() */</span><span style=3D"color:#000"> <br></span>=
<span style=3D"color:#660">}</span><span style=3D"color:#000"><br></span></=
div></code></div>
=A0<br>Those *all* take ranges that can be zero sized, so his proposal is *=
not* a replacement for those interfaces.<br><br></div><blockquote class=3D"=
gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-=
left:1ex">
Be that as it may, if you wish to persist with this notion that "empty=
=3D=3D invalid =3D=3D error", then you need to be <i>serious</i> abou=
t it. And that means you <i>need</i> to throw an exception on any circumsta=
nce that would result in an empty range. Merely being "undefined behav=
ior" isn't enough, even by your own standard:</blockquote>
<div><br>I disagree.=A0 Should he write it up and come to a committee meeti=
ng to present it, it will not change my vote of "strongly against"=
; whether it is undefined or throws an exception.<br></div></div>-- <br>
=A0Nevin ":-)" Liber=A0 <mailto:<a href=3D"mailto:nevin@evilov=
erlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=A0 (847) 691-1=
404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--20cf306f750c51c35b04df5e0a79--
.
Author: Jonathan Wakely <cxx@kayari.org>
Date: Tue, 18 Jun 2013 10:54:42 -0700 (PDT)
Raw View
------=_Part_2568_22152130.1371578082756
Content-Type: text/plain; charset=ISO-8859-1
On Monday, June 17, 2013 6:52:40 PM UTC+1, justin carlson wrote:
>
>
> As a reference does not represent absence by design:
> void foo(const T&);
>
> neither does a sequence:
> void foo(sequence<T>);
>
> That's a better way to think of it (i.e. not a range which may be empty).
> So the problem I was trying to solve when implementing sequences was
> "References are great - How can I express that for arrays?".
>
Then this is utterly useless for me, I want something like array_ref
instead.
I can't think of a time when I've needed the type system to distinguish
between contiguous sequences of zero length and contiguous sequences of
non-zero-length, because most generic operations I want to do on a sequence
still work perfectly well if it's empty. If there are uses for it I don't
think they're common enough to standardize.
Before you spend *any* more time on the proposal please, PLEASE rename it.
A "sequence" implies some association with sequence containers and the
distinguishing feature of your type is non-empty. I think a lot of time has
been wasted in this thread because of the mental mismatch people have
between their idea of a sequence and the fact you're reusing that name for
a non-empty contiguous buffer.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2568_22152130.1371578082756
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Monday, June 17, 2013 6:52:40 PM UTC+1, justin carlson wrote:<bl=
ockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border=
-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-wor=
d"><div><br><div><div>As a reference does not represent absence by design:<=
/div><div> void foo(const T&);</div><div><br></div><div>neither do=
es a sequence:</div><div> void foo(sequence<T>);</div><div><br><=
/div><div>That's a better way to think of it (i.e. not a range which may be=
empty). So the problem I was trying to solve when implementing sequences w=
as "References are great - How can I express that for arrays?".</div></div>=
</div></div></blockquote><div><br>Then this is utterly useless for me, I wa=
nt something like array_ref instead.<br><br>I can't think of a time when I'=
ve needed the type system to distinguish between contiguous sequences of ze=
ro length and contiguous sequences of non-zero-length, because most generic=
operations I want to do on a sequence still work perfectly well if it's em=
pty. If there are uses for it I don't think they're common enough to =
standardize.<br><br>Before you spend *any* more time on the proposal please=
, PLEASE rename it. A "sequence" implies some association with sequen=
ce containers and the distinguishing feature of your type is non-empty. I t=
hink a lot of time has been wasted in this thread because of the mental mis=
match people have between their idea of a sequence and the fact you're reus=
ing that name for a non-empty contiguous buffer.<br> <br> <br></d=
iv>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
------=_Part_2568_22152130.1371578082756--
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Wed, 19 Jun 2013 08:52:20 -0400
Raw View
--Apple-Mail=_6F11578E-D18C-4848-A534-95E649F8DD40
Content-Type: text/plain; charset=ISO-8859-1
On Jun 17, 2013, at 2:42 PM, Alex B <devalexb@gmail.com> wrote:
>
> As a reference does not represent absence by design:
> void foo(const T&);
>
> neither does a sequence:
> void foo(sequence<T>);
>
> That's a better way to think of it (i.e. not a range which may be empty).
>
> I still don't get it. For me, the purpose of a sequence is to replace this kind of function:
> void foo(const vector<T>&); // not "const T&" like in your example
>
> by this:
> void foo(sequence<T>);
>
> That is the most obvious use-case I can see; a simple drop-in replacement in the declaration without any change in the logic/meaning.
> But are you suggesting that your use-case is to replace a function taking a reference to a single element (not a container) should take a sequence instead?
No. It was just an analogy. Like: Reference is to single object as sequence is to array -- Neither represent absence in the sense that they both refer to *something* (one or multiple things in the case of a sequence).
> It would really help to understand what is the intent of your class if you bring real-world code samples. For example, show an existing (real) function and a new version that would benefit from sequences.
It was as you understood it before the confusing analogy:
float median(sequence<float> p) {...}
float n[2] = {3,9};
float m(median(n));
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--Apple-Mail=_6F11578E-D18C-4848-A534-95E649F8DD40
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Diso-8859-1"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mo=
de: space; -webkit-line-break: after-white-space; "><br><div><div>On Jun 17=
, 2013, at 2:42 PM, Alex B <<a href=3D"mailto:devalexb@gmail.com">devale=
xb@gmail.com</a>> wrote:</div><br class=3D"Apple-interchange-newline"><b=
lockquote type=3D"cite"><div dir=3D"ltr"><br><div class=3D"gmail_extra"><di=
v class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style=3D"word-w=
rap:break-word"><div>As a reference does not represent absence by design:</=
div>
<div> void foo(const T&);</div><div><br></div><div>neither does a =
sequence:</div><div> void foo(sequence<T>);</div><div><br></div>=
<div>That's a better way to think of it (i.e. not a range which may be empt=
y).</div>
</div></blockquote><div><br></div><div style=3D"">I still don't get it. For=
me, the purpose of a sequence is to replace this kind of function:</div><d=
iv style=3D""> void foo(const vector<T>&); // <b><u>=
not </u></b>"const T&" like in your example<br>
</div><div style=3D""><br></div><div style=3D"">by this:</div><div style=3D=
""> void foo(sequence<T>);</div><div style=3D""><br></div><div =
style=3D"">That is the most obvious use-case I can see; a simple drop-in re=
placement in the declaration without any change in the logic/meaning.</div>
<div style=3D"">But are you suggesting that your use-case is to replace a f=
unction taking a <i>reference to a single element</i> (not a container) sho=
uld take a sequence instead?</div></div></div></div></blockquote><div><br><=
/div>No. It was just an analogy. Like: Reference is to single object as seq=
uence is to array -- Neither represent absence in the sense that they both =
refer to *something* (one or multiple things in the case of a sequence).</d=
iv><div><br><blockquote type=3D"cite"><div dir=3D"ltr"><div class=3D"gmail_=
extra"><div class=3D"gmail_quote">
<div style=3D"">It would really help to understand what is the intent of yo=
ur class if you bring real-world code samples. For example, show an ex=
isting (real) function and a new version that would benefit from sequences.=
</div></div></div></div></blockquote><div><br></div></div>It was as you und=
erstood it before the confusing analogy:<div><br></div><div><span class=3D"=
Apple-tab-span" style=3D"white-space: pre; "> </span>float median(sequence&=
lt;float> p) {...}</div><div><br></div><div><span class=3D"Apple-tab-spa=
n" style=3D"white-space:pre"> </span>float n[2] =3D {3,9};</div><div><=
span class=3D"Apple-tab-span" style=3D"white-space:pre"> </span>float =
m(median(n));</div><div><br></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--Apple-Mail=_6F11578E-D18C-4848-A534-95E649F8DD40--
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Wed, 19 Jun 2013 09:48:53 -0400
Raw View
--Apple-Mail=_EA1EB956-CA28-4061-8A53-DBB126433111
Content-Type: text/plain; charset=ISO-8859-1
On Jun 17, 2013, at 2:47 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
> On 15 June 2013 21:55, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>
> The entire rest of the world disagrees with you. Virtually every API that takes a sequence of contiguously allocated objects will accept an empty sequence thereof, regardless of how that API might define an empty sequence.
>
> Including *every* API he mentioned:
>
> size_t foo(const int* elements, size_t n);
> size_t foo(const std::array<int, N>&);
> size_t foo(const std::vector<int>&);
> size_t foo(const std::vector<int,SomeSpecialAllocator>&);
>
> template<typename TArbitraryContainer>
> size_t foo(const TArbitraryContainer&) {
> /* e.g. TArbitraryContainer must support subscripting and size() */
> }
>
> Those *all* take ranges that can be zero sized, so his proposal is *not* a replacement for those interfaces.
Based on what? Have you broken into my systems and proven that those APIs "*all* take ranges that can be zero sized"?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--Apple-Mail=_EA1EB956-CA28-4061-8A53-DBB126433111
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Diso-8859-1"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mo=
de: space; -webkit-line-break: after-white-space; "><br><div><div>On Jun 17=
, 2013, at 2:47 PM, Nevin Liber <<a href=3D"mailto:nevin@eviloverlord.co=
m">nevin@eviloverlord.com</a>> wrote:</div><blockquote type=3D"cite">On =
15 June 2013 21:55, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:jmc=
kesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span> wrot=
e:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D=
"margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(=
204, 204, 204); border-left-style: solid; padding-left: 1ex; position: stat=
ic; z-index: auto; ">
<br><br>The entire rest of the world disagrees with=20
you. Virtually every API that takes a sequence of contiguously allocated ob=
jects will accept an empty sequence thereof, regardless of how that API mig=
ht define an empty sequence.<br></blockquote><div><br>Including *every* API=
he mentioned:<br>
<br><div style=3D"background-color:rgb(250,250,250);border:1px solid rgb(18=
7,187,187);word-wrap:break-word"><code><div><span style=3D"">size_t foo</sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#008">const</spa=
n><span style=3D""> </span><span style=3D"color:#008">int</span><span style=
=3D"color:#660">*</span><span style=3D""> elements</span><span style=3D"col=
or:#660">,</span><span style=3D""> size_t n</span><span style=3D"color:#660=
">);</span><span style=3D""><br>
</span><span style=3D"">size_t foo</span><span style=3D"color:#660">(</span=
><span style=3D"color:#008">const</span><span style=3D""> std</span><span s=
tyle=3D"color:#660">::</span><span style=3D"">array</span><span style=3D"co=
lor:#660"><</span><span style=3D"color:#008">int</span><span style=3D"co=
lor:#660">,</span><span style=3D""> N</span><span style=3D"color:#660">>=
&);</span></div>
<div><span style=3D"">size_t foo</span><span style=3D"color:#660">(</span><=
span style=3D"color:#008">const</span><span style=3D""> std</span><span sty=
le=3D"color:#660">::</span><span style=3D"">vector</span><span style=3D"col=
or:#080"><int></span><span style=3D"color:#660">&);</span></div>
<div><span style=3D"">size_t foo</span><span style=3D"color:#660">(</span><=
span style=3D"color:#008">const</span><span style=3D""> std</span><span sty=
le=3D"color:#660">::</span><span style=3D"">vector</span><span style=3D"col=
or:#660"><</span><span style=3D"color:#008">int</span><span style=3D"col=
or:#660">,</span><span style=3D"color:#606">SomeSpecialAllocator</span><spa=
n style=3D"color:#660">>&);</span></div>
<div><span style=3D""></span><span style=3D"color:#008"><br>template</span>=
<span style=3D"color:#660"><</span><span style=3D"color:#008">typename</=
span><span style=3D""> </span><span style=3D"color:#606">TArbitraryContaine=
r</span><span style=3D"color:#660">></span></div>
<div><span style=3D"">size_t foo</span><span style=3D"color:#660">(</span><=
span style=3D"color:#008">const</span><span style=3D""> </span><span style=
=3D"color:#606">TArbitraryContainer</span><span style=3D"color:#660">&)=
</span><span style=3D""> </span><span style=3D"color:#660">{</span><span st=
yle=3D""><br>
</span><span style=3D"color:#800">/* e.g. TArbitraryContainer must su=
pport subscripting and size() */</span><span style=3D""> <br></span><span s=
tyle=3D"color:#660">}</span><span style=3D""><br></span></div></code></div>
<br>Those *all* take ranges that can be zero sized, so his proposal i=
s *not* a replacement for those interfaces.</div></div></blockquote><br></d=
iv>Based on what? Have you broken into my systems and proven that those API=
s "*all* take ranges that can be zero sized"?<div><br></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--Apple-Mail=_EA1EB956-CA28-4061-8A53-DBB126433111--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Wed, 19 Jun 2013 09:17:37 -0500
Raw View
--001a1133dde64b112f04df828011
Content-Type: text/plain; charset=ISO-8859-1
On 19 June 2013 08:48, justin carlson <carrierandoperator@yahoo.co.uk>wrote:
>
> On Jun 17, 2013, at 2:47 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
>
> On 15 June 2013 21:55, Nicol Bolas <jmckesson@gmail.com> wrote:
>
>>
>>
>> The entire rest of the world disagrees with you. Virtually every API that
>> takes a sequence of contiguously allocated objects will accept an empty
>> sequence thereof, regardless of how that API might define an empty sequence.
>>
>
> Including *every* API he mentioned:
>
> size_t foo(const int* elements, size_t n);
> size_t foo(const std::array<int, N>&);
> size_t foo(const std::vector<int>&);
> size_t foo(const std::vector<int,SomeSpecialAllocator>&);
>
> template<typename TArbitraryContainer>
> size_t foo(const TArbitraryContainer&) {
> /* e.g. TArbitraryContainer must support subscripting and size() */
> }
>
> Those *all* take ranges that can be zero sized, so his proposal is *not* a
> replacement for those interfaces.
>
>
> Based on what? Have you broken into my systems and proven that those APIs
> "*all* take ranges that can be zero sized"?
>
Zero sized is perfectly valid for *all* those types, so in the absence of
other documentation, my statement stands.
I'm bowing out of this conversation. Good luck with your proposal.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1133dde64b112f04df828011
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On 19 June 2013 08:48, justin carlson <span dir=3D"ltr"><<a href=3D"mail=
to:carrierandoperator@yahoo.co.uk" target=3D"_blank">carrierandoperator@yah=
oo.co.uk</a>></span> wrote:<br><div class=3D"gmail_quote"><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;p=
adding-left:1ex">
<div style=3D"word-wrap:break-word"><div class=3D"im"><br><div><div>On Jun =
17, 2013, at 2:47 PM, Nevin Liber <<a href=3D"mailto:nevin@eviloverlord.=
com" target=3D"_blank">nevin@eviloverlord.com</a>> wrote:</div><blockquo=
te type=3D"cite">
On 15 June 2013 21:55, Nicol Bolas <span dir=3D"ltr"><<a href=3D"mailto:=
jmckesson@gmail.com" target=3D"_blank">jmckesson@gmail.com</a>></span> w=
rote:<br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(20=
4,204,204);border-left-style:solid;padding-left:1ex">
<br><br>The entire rest of the world disagrees with=20
you. Virtually every API that takes a sequence of contiguously allocated ob=
jects will accept an empty sequence thereof, regardless of how that API mig=
ht define an empty sequence.<br></blockquote><div><br>Including *every* API=
he mentioned:<br>
<br><div style=3D"background-color:rgb(250,250,250);border:1px solid rgb(18=
7,187,187);word-wrap:break-word"><code><div><span>size_t foo</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#008">const</span><span> </=
span><span style=3D"color:#008">int</span><span style=3D"color:#660">*</spa=
n><span> elements</span><span style=3D"color:#660">,</span><span> size_t n<=
/span><span style=3D"color:#660">);</span><span><br>
</span><span>size_t foo</span><span style=3D"color:#660">(</span><span styl=
e=3D"color:#008">const</span><span> std</span><span style=3D"color:#660">::=
</span><span>array</span><span style=3D"color:#660"><</span><span style=
=3D"color:#008">int</span><span style=3D"color:#660">,</span><span> N</span=
><span style=3D"color:#660">>&);</span></div>
<div><span>size_t foo</span><span style=3D"color:#660">(</span><span style=
=3D"color:#008">const</span><span> std</span><span style=3D"color:#660">::<=
/span><span>vector</span><span style=3D"color:#080"><int></span><span=
style=3D"color:#660">&);</span></div>
<div><span>size_t foo</span><span style=3D"color:#660">(</span><span style=
=3D"color:#008">const</span><span> std</span><span style=3D"color:#660">::<=
/span><span>vector</span><span style=3D"color:#660"><</span><span style=
=3D"color:#008">int</span><span style=3D"color:#660">,</span><span style=3D=
"color:#606">SomeSpecialAllocator</span><span style=3D"color:#660">>&=
;);</span></div>
<div><span></span><span style=3D"color:#008"><br>template</span><span style=
=3D"color:#660"><</span><span style=3D"color:#008">typename</span><span>=
</span><span style=3D"color:#606">TArbitraryContainer</span><span style=3D=
"color:#660">></span></div>
<div><span>size_t foo</span><span style=3D"color:#660">(</span><span style=
=3D"color:#008">const</span><span> </span><span style=3D"color:#606">TArbit=
raryContainer</span><span style=3D"color:#660">&)</span><span> </span><=
span style=3D"color:#660">{</span><span><br>
=A0</span><span style=3D"color:#800">/* e.g. TArbitraryContainer must suppo=
rt subscripting and size() */</span><span> <br></span><span style=3D"color:=
#660">}</span><span><br></span></div></code></div>
=A0<br>Those *all* take ranges that can be zero sized, so his proposal is *=
not* a replacement for those interfaces.</div></div></blockquote><br></div>=
</div>Based on what? Have you broken into my systems and proven that those =
APIs "*all* take ranges that can be zero sized"?</div>
</blockquote><div><br>Zero sized is perfectly valid for *all* those types, =
so in the absence of other documentation, my statement stands.<br><br>I'=
;m bowing out of this conversation.=A0 Good luck with your proposal.<br>
</div>
</div>-- <br>=A0Nevin ":-)" Liber=A0 <mailto:<a href=3D"mailto=
:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a>>=
=A0 (847) 691-1404
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--001a1133dde64b112f04df828011--
.
Author: Alex B <devalexb@gmail.com>
Date: Wed, 19 Jun 2013 14:14:17 -0400
Raw View
--001a11c34da04cbf3304df85cc76
Content-Type: text/plain; charset=ISO-8859-1
> It was as you understood it before the confusing analogy:
>
> float median(sequence<float> p) {...}
>
> float n[2] = {3,9};
> float m(median(n));
>
Your original function (prior to sequences) probably was:
float median(const vector<float>& p) {...}
In that case, since it is perfectly valid to have an empty vector, it is
your *function *that has the precondition p.size() > 0. It is the
*responsibilty
of your function* to define what will happen if p is empty; will it be UB,
exception, assert, default return value, etc?
What you want to do is carry over the precondition from the function to the
range itself. To me it doesn't make sense to have this for "sequences" but
not for other containers/ranges in the standard. It might make sense in
your own code, but not in the standard where uniformity should be kept
(isn't it why we call it a *standard*?). So yes, you are actually
challenging the whole standard by breaking its uniformity. You can keep
saying that sequences should not be considered as ranges so we should not
care much about uniformity; yet they have the (almost) same
interface/signature. You *want it* to be something different but concretely
it really *is* a range class.
If you really want to continue pushing that way, I really don't know what
else I can tell...
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a11c34da04cbf3304df85cc76
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div style=3D"word-wrap:break-word">It was a=
s you understood it before the confusing analogy:<div>
<br></div><div><span style=3D"white-space:pre-wrap"> </span>float median(se=
quence<float> p) {...}</div><div><br></div><div><span style=3D"white-=
space:pre-wrap"> </span>float=A0n[2] =3D {3,9};</div><div><span style=3D"wh=
ite-space:pre-wrap"> </span>float=A0m(median(n));</div>
</div></blockquote></div><br></div><div class=3D"gmail_extra" style>Your or=
iginal function (prior to sequences) probably was:</div><div class=3D"gmail=
_extra" style>=A0 =A0float median(const vector<float>& p) {...}</=
div>
<div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra" style=
>In that case, since it is perfectly valid to have an empty vector, it is y=
our <b>function </b>that has the precondition p.size() > 0. It is the <b=
>responsibilty of your function</b>=A0to define what will happen if p is em=
pty; will it be UB, exception, assert, default return value, etc?</div>
<div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra" style=
>What you want to do is carry over the precondition from the function to th=
e range itself. To me it doesn't make sense to have this for "sequ=
ences" but not for other containers/ranges in the standard. It might m=
ake sense in your own code, but not in the standard where uniformity should=
be kept (isn't it why we call it a=A0<i>standard</i>?). So yes, you ar=
e actually challenging the whole standard by breaking its uniformity. You c=
an keep saying that sequences should not be considered as ranges so we shou=
ld not care much about uniformity; yet they have the (almost) same interfac=
e/signature. You <i>want it</i>=A0to be something different but concretely =
it really <i>is</i>=A0a range class.</div>
<div class=3D"gmail_extra" style><br></div><div class=3D"gmail_extra" style=
>If you really want to continue pushing that way, I really don't know w=
hat else I can tell...</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--001a11c34da04cbf3304df85cc76--
.
Author: justin carlson <carrierandoperator@yahoo.co.uk>
Date: Wed, 19 Jun 2013 17:42:58 -0400
Raw View
--Apple-Mail=_14C94877-E7D6-4DF9-B66F-DE12BE08EAEF
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=ISO-8859-1
On Jun 19, 2013, at 2:14 PM, Alex B <devalexb@gmail.com> wrote:
>=20
> It was as you understood it before the confusing analogy:
>=20
> float median(sequence<float> p) {...}
>=20
> float n[2] =3D {3,9};
> float m(median(n));
>=20
> Your original function (prior to sequences) probably was:
> float median(const vector<float>& p) {...}
>=20
> In that case, since it is perfectly valid to have an empty vector, it is =
your function that has the precondition p.size() > 0. It is the responsibil=
ty of your function to define what will happen if p is empty; will it be UB=
, exception, assert, default return value, etc?
>=20
> What you want to do is carry over the precondition from the function to t=
he range itself.
Right, like the disuse of the form:
void f(big_object* p) {
if (p =3D=3D NULL) {
Error
}
...
}
once the ability to use:
void f(big_object& p) {
...
}
became available in the language and adopted by developers. The parameter t=
ype immediately informs the reader very exact requirements of the API, whil=
e ruling out classes of (not-so-unusual) ambiguities on both sides.
> If you really want to continue pushing that way, I really don't know what=
else I can tell...
Agreed. Thanks for your input.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_14C94877-E7D6-4DF9-B66F-DE12BE08EAEF
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=ISO-8859-1
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Diso-8859-1"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mo=
de: space; -webkit-line-break: after-white-space; "><br><div><div>On Jun 19=
, 2013, at 2:14 PM, Alex B <<a href=3D"mailto:devalexb@gmail.com">devale=
xb@gmail.com</a>> wrote:</div><br class=3D"Apple-interchange-newline"><b=
lockquote type=3D"cite"><div dir=3D"ltr"><br><div class=3D"gmail_extra"><di=
v class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0=
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style=3D"word-w=
rap:break-word">It was as you understood it before the confusing analogy:<d=
iv>
<br></div><div><span style=3D"white-space:pre-wrap"> </span>float median(se=
quence<float> p) {...}</div><div><br></div><div><span style=3D"white-=
space:pre-wrap"> </span>float n[2] =3D {3,9};</div><div><span style=3D=
"white-space:pre-wrap"> </span>float m(median(n));</div>
</div></blockquote></div><br></div><div class=3D"gmail_extra" style=3D"">Yo=
ur original function (prior to sequences) probably was:</div><div class=3D"=
gmail_extra" style=3D""> float median(const vector<float>=
& p) {...}</div>
<div class=3D"gmail_extra" style=3D""><br></div><div class=3D"gmail_extra" =
style=3D"">In that case, since it is perfectly valid to have an empty vecto=
r, it is your <b>function </b>that has the precondition p.size() > 0. It=
is the <b>responsibilty of your function</b> to define what will happ=
en if p is empty; will it be UB, exception, assert, default return value, e=
tc?</div>
<div class=3D"gmail_extra" style=3D""><br></div><div class=3D"gmail_extra" =
style=3D"">What you want to do is carry over the precondition from the func=
tion to the range itself.</div></div></blockquote><div><br></div><div>Right=
, like the disuse of the form:</div><div><span style=3D"font-family: 'Couri=
er New'; ">void f(big_object* p) {</span></div><div><font face=3D"Courier N=
ew"> if (p =3D=3D NULL) {</font></div><div><font face=3D"Courier New"=
> Error</font></div><div><font face=3D"Courier New"> }</=
font></div><div><font face=3D"Courier New"> ...</font></div><div><fon=
t face=3D"Courier New">}</font></div><div><br></div><div>once the ability t=
o use:</div><div><div><font face=3D"Courier New">void f(big_object& p) =
{</font></div><div><font face=3D"Courier New"> ...</font></div><div><=
font face=3D"Courier New">}</font></div><div><br></div><div>became availabl=
e in the language and adopted by developers. The parameter type immediately=
informs the reader very exact requirements of the API, while ruling out cl=
asses of (not-so-unusual) ambiguities on both sides.</div></div><div><br></=
div><blockquote type=3D"cite"><div dir=3D"ltr"><div class=3D"gmail_extra" s=
tyle=3D"">If you really want to continue pushing that way, I really don't k=
now what else I can tell...</div></div></blockquote><div><br></div></div>Ag=
reed. Thanks for your input.<div><br></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
<br />
<br />
--Apple-Mail=_14C94877-E7D6-4DF9-B66F-DE12BE08EAEF--
.
Author: carrierandoperator@yahoo.co.uk
Date: Fri, 21 Jun 2013 10:43:23 -0700 (PDT)
Raw View
------=_Part_740_19016568.1371836603117
Content-Type: text/plain; charset=ISO-8859-1
Absence because I've been busy. I'm letting you know this was the tipping
point in the conversation. I've started working on a type which is less
foreign. Thanks.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_740_19016568.1371836603117
Content-Type: text/html; charset=ISO-8859-1
Absence because I've been busy. I'm letting you know this was the tipping point in the conversation. I've started working on a type which is less foreign. Thanks.<br><br><br>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.<br />
To post to this group, send email to std-proposals@isocpp.org.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />
<br />
<br />
------=_Part_740_19016568.1371836603117--
.