Is there any interest in non-owning pointer-like types?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
37 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Is there any interest in non-owning pointer-like types?

Joseph Thomson
For some time, I have been developing a pair of non-owning pointer-like
types that I am currently calling `observer_ptr` and `observer`. I had
planned to propose their addition to the C++ standard library, but I have
been informed by the author of the original `observer_ptr` proposal
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282.pdf> that
the ISO C++ committee has rejected his proposal and made clear that it
feels there is no place in the standard library for such types, believing
that this role is filled to a satisfactory degree by regular pointers. I
wholeheartedly disagree with this assessment, so I am bringing my proposal
here instead.

The `observer_ptr<T>` class template is a pointer-like type that does not
do any resource management, and is intended to be used in place of `T*`
wherever `T*` is used as a non-owning reference to an object of type `T`.
`observer_ptr<T>` has three main advantages over `T*`:

   1. `T&` is implicitly convertible to `observer_ptr<T>` which, unlike `T*`,
   makes it *type-safe*. `T*` can represent things that are not
   conceptually objects of type `T`: arrays, strings, iterators. No
   implicit conversion from `T*` means that these things cannot implicitly
   convert to `observer_ptr<T>`. Pointers aren't even required to point to
   valid objects (e.g. a past-the-end iterator). Conversely, in a well-formed
   program, `T&` is *always* a valid object of type `T`.
   2. `observer_ptr<T>` documents its purpose. This is really a side-effect
   of it being type-safe (a type should have a single, specific purpose), but
   it's worth mentioning. Conversely, when you see `T*`, it may not be
   immediately obvious what it represents.
   3. `observer_ptr<T>` has a minimal interface, which makes it harder to
   misuse than `T*`; for example, `observer_ptr<T>` has no pointer
   arithmetic operators, no array subscript operator, no conversion to
   `void*`.

The `observer<T>` class template is a counterpart to `observer_ptr<T>` that
has *no null state*; it cannot be default constructed, constructed from
`nullptr_t` or constructed from `T*`, and it does not contextually convert
to `bool`. The only way to create an `observer<T>` is from `T&`. This
allows a "not null" precondition to be enforced at compile-time, rather
than having to worry about pointers being null at run-time.

Just to give you an idea of the current syntax, here is a simple tree node
type (where the nodes do not own their children) implemented using
`observer_ptr` and `observer`:

class node
{
public:
  node() = default;
  node(node const&) = delete;
  node& operator=(node const&) = delete;
  node(node&&) = delete;
  node& operator=(node&&) = delete;

  void set_parent(observer_ptr<node> new_parent) {
    if (parent) parent->remove_child(*this);
    parent = new_parent;
    if (parent) parent->add_child(*this);
  }

  observer_ptr<node> get_parent() const {
    return parent;
  }

  size_t get_child_count() const {
    return children.size();
  }

  observer<node> get_child(size_t index) const {
    return children[index];
  }

private:
  observer_ptr<node> parent;
  vector<observer<node>> children;

  void add_child(observer<node> child) {
    children.push_back(child);
  }
  void remove_child(observer<node> child) {
    children.erase(find(begin(children), end(children), child));
  }
};

And a contrived usage example:

node a, b, c;


b.set_parent(a);    // conversion from `T&`
c.set_parent(b);

observer_ptr<node> x = c.get_parent();

if (x)              // conversion to `bool`
{
  observer<node> y = x->get_child(0);

  assert(y == c);   // comparison with `T&`

  y->set_parent(a);
  b.set_parent(y);  // conversion from `observer<T>`
                       to `observer_ptr<T>`
}

A project with a working implementation
<https://github.com/hpesoj/cpp-observer/blob/master/api/observer.hpp> and
full test suite
<https://github.com/hpesoj/cpp-observer/blob/master/tests/observer_tests.cpp>
can be found here <https://github.com/hpesoj/cpp-observer>.

Regards,

Joseph

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Rob Stewart-2
On February 1, 2017 2:47:54 AM EST, Joseph Thomson <[hidden email]> wrote:
> For some time, I have been developing a pair of non-owning
> pointer-like
> types that I am currently calling `observer_ptr` and `observer`.

[snip]

> The `observer_ptr<T>` class template is a pointer-like type that does
> not
> do any resource management, and is intended to be used in place of
> `T*`
> wherever `T*` is used as a non-owning reference to an object of type
> `T`.
> `observer_ptr<T>` has three main advantages over `T*`:
>
> 1. `T&` is implicitly convertible to `observer_ptr<T>` which, unlike
> `T*`,
>    makes it *type-safe*. `T*` can represent things that are not
>    conceptually objects of type `T`: arrays, strings, iterators. No
> implicit conversion from `T*` means that these things cannot
> implicitly
> convert to `observer_ptr<T>`. Pointers aren't even required to point
> to
> valid objects (e.g. a past-the-end iterator). Conversely, in a
> well-formed
>    program, `T&` is *always* a valid object of type `T`.
> 2. `observer_ptr<T>` documents its purpose. This is really a
> side-effect
> of it being type-safe (a type should have a single, specific purpose),
> but
>    it's worth mentioning. Conversely, when you see `T*`, it may not be
>    immediately obvious what it represents.
> 3. `observer_ptr<T>` has a minimal interface, which makes it harder to
>    misuse than `T*`; for example, `observer_ptr<T>` has no pointer
>    arithmetic operators, no array subscript operator, no conversion to
>    `void*`.

Can observer_ptr refer to no object? If not, why not just use T &? If so, why not just use optional<T>?

> The `observer<T>` class template is a counterpart to `observer_ptr<T>`
> that
> has *no null state*; it cannot be default constructed, constructed
> from
> `nullptr_t` or constructed from `T*`, and it does not contextually
> convert
> to `bool`. The only way to create an `observer<T>` is from `T&`. This
> allows a "not null" precondition to be enforced at compile-time,
> rather
> than having to worry about pointers being null at run-time.

How is this better than T &?

--
Rob

(Sent from my portable computation device.)

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Oswin Krause
Hi,

> Can observer_ptr refer to no object? If not, why not just use T &? If
> so, why not just use optional<T>?

As far as i understood it, it is still assignable, unlike T&.


For me, the biggest problem of the proposal is that observer_ptr<T> is
implicitely constructed from T&. In my code I often use:

Foo a;
Bar b(&a);//&a signals that b only references to a, but does not copy
it.

Now, when I write

Bar b(a); //so is a now copied?

While the interface is clearer in documentation, the usage is less
clear!

Best,
Oswin

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Joseph Thomson
Quick note: I just subscribed to the list, and perhaps because I had
"digest mode" switched on until just now, this was the first reply I
received. Are there any other replies I haven't seen?

On Wed, Feb 1, 2017 at 6:24 PM, Oswin Krause <
[hidden email]> wrote:

> Hi,
>
> Can observer_ptr refer to no object? If not, why not just use T &? If
>> so, why not just use optional<T>?
>>
>
> As far as i understood it, it is still assignable, unlike T&.
>

`observer_ptr<T>` can be null; `observer<T>` cannot. `T&` is not the same
in a number of ways:

   - `T&` cannot be "rebound" after construction.
   - `T&` makes containing classes non-copy assignable by default
   - `T&` cannot be stored in arrays
   - `T&` cannot be stored in containers (though I saw maybe this is a
   feature being added to the C++ standard?)
   - `T&` has value assignment and comparison semantics (they operate on
   the referenced value); the observer types have reference (pointer-like)
   assignment and comparison semantics. They behave very differently with
   algorithms and containers (

`reference_wrapper` has reference assignment semantics, which makes it work
properly in containers, but it still has value comparison semantics.

Essentially, `T&` (and `reference_wrapper<T>`) is not a pointer type, and
has totally different semantics. `observer_ptr` and `observer` have pointer
semantics and are useful where pointers would be useful.

For me, the biggest problem of the proposal is that observer_ptr<T> is

> implicitely constructed from T&. In my code I often use:
>
> Foo a;
> Bar b(&a);//&a signals that b only references to a, but does not copy it.
>
> Now, when I write
>
> Bar b(a); //so is a now copied?
>
> While the interface is clearer in documentation, the usage is less clear!
>

I personally have used this pattern in code before without confusion:

bar(foo const& f) : m_f(&f) {}

Indeed, the documented interface is clearer if you use `observer<foo
const>`, but the calling code looks the same.

I did anticipate that this might be a problem for some people (though I am
personally comfortable with it). If this is a widespread concern, the
implicit conversion from `T&` could be removed `make_observer` would become
the recommended way to create an `observer`:

Bar b(make_observer(a));

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Olaf van der Spek-3
In reply to this post by Rob Stewart-2
On Wed, Feb 1, 2017 at 10:27 AM, Rob Stewart <[hidden email]> wrote:
> On February 1, 2017 2:47:54 AM EST, Joseph Thomson <[hidden email]> wrote:
> Can observer_ptr refer to no object? If not, why not just use T &? If so, why not just use optional<T>?

optional<T> is a value, not a pointer/reference..


--
Olaf

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Olaf van der Spek-3
In reply to this post by Oswin Krause
On Wed, Feb 1, 2017 at 11:24 AM, Oswin Krause
<[hidden email]> wrote:

> For me, the biggest problem of the proposal is that observer_ptr<T> is
> implicitely constructed from T&. In my code I often use:
>
> Foo a;
> Bar b(&a);//&a signals that b only references to a, but does not copy it.
>
> Now, when I write
>
> Bar b(a); //so is a now copied?
>
> While the interface is clearer in documentation, the usage is less clear!

IMO using pointers instead of references to indicate something isn't
copied is bad practice.. the language is C++, not C.


--
Olaf

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Oswin Krause
On 2017-02-01 12:02, Olaf van der Spek wrote:

> On Wed, Feb 1, 2017 at 11:24 AM, Oswin Krause
> <[hidden email]> wrote:
>> For me, the biggest problem of the proposal is that observer_ptr<T> is
>> implicitely constructed from T&. In my code I often use:
>>
>> Foo a;
>> Bar b(&a);//&a signals that b only references to a, but does not copy
>> it.
>>
>> Now, when I write
>>
>> Bar b(a); //so is a now copied?
>>
>> While the interface is clearer in documentation, the usage is less
>> clear!
>
> IMO using pointers instead of references to indicate something isn't
> copied is bad practice.. the language is C++, not C.


This is not a C vs C++ thing.

But assume it was. How would you indicate that in C++? It should be
clear without looking at the reference whether it is okay for a to go
out of scope before b or not.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Olaf van der Spek-3
On Wed, Feb 1, 2017 at 12:39 PM, Oswin Krause
<[hidden email]> wrote:

> On 2017-02-01 12:02, Olaf van der Spek wrote:
>>
>> On Wed, Feb 1, 2017 at 11:24 AM, Oswin Krause
>> <[hidden email]> wrote:
>>>
>>> For me, the biggest problem of the proposal is that observer_ptr<T> is
>>> implicitely constructed from T&. In my code I often use:
>>>
>>> Foo a;
>>> Bar b(&a);//&a signals that b only references to a, but does not copy it.
>>>
>>> Now, when I write
>>>
>>> Bar b(a); //so is a now copied?
>>>
>>> While the interface is clearer in documentation, the usage is less clear!
>>
>>
>> IMO using pointers instead of references to indicate something isn't
>> copied is bad practice.. the language is C++, not C.
>
>
>
> This is not a C vs C++ thing.
>
> But assume it was. How would you indicate that in C++? It should be clear
> without looking at the reference whether it is okay for a to go out of scope
> before b or not.

There's no way to indicate that, AFAIK.

--
Olaf

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Joseph Thomson
On 1 Feb 2017 7:51 p.m., "Olaf van der Spek" <[hidden email]> wrote:

On Wed, Feb 1, 2017 at 12:39 PM, Oswin Krause
<[hidden email]> wrote:

> On 2017-02-01 12:02, Olaf van der Spek wrote:
>>
>> On Wed, Feb 1, 2017 at 11:24 AM, Oswin Krause
>> <[hidden email]> wrote:
>>>
>>> For me, the biggest problem of the proposal is that observer_ptr<T> is
>>> implicitely constructed from T&. In my code I often use:
>>>
>>> Foo a;
>>> Bar b(&a);//&a signals that b only references to a, but does not copy
it.
>>>
>>> Now, when I write
>>>
>>> Bar b(a); //so is a now copied?
>>>
>>> While the interface is clearer in documentation, the usage is less
clear!

>>
>>
>> IMO using pointers instead of references to indicate something isn't
>> copied is bad practice.. the language is C++, not C.
>
>
>
> This is not a C vs C++ thing.
>
> But assume it was. How would you indicate that in C++? It should be clear
> without looking at the reference whether it is okay for a to go out of
scope
> before b or not.

There's no way to indicate that, AFAIK.


The way to indicate it is to require explicit conversion from `T&` to your
pointer-like type. `make_observer` can play the role of a type-safe `&`. I
would be happy to remove implicit conversion from `T&` if it is agreed to
be undesirable.

Joseph

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Brook Milligan-2
In reply to this post by Joseph Thomson

> On Feb 1, 2017, at 12:47 AM, Joseph Thomson <[hidden email]> wrote:
>
> The `observer_ptr<T>` class template is a pointer-like type that does not
> do any resource management, and is intended to be used in place of `T*`
> wherever `T*` is used as a non-owning reference to an object of type `T`.
> `observer_ptr<T>` has three main advantages over `T*`:

From my own experience, which includes writing my own version of exactly what you are describing and using it extensively in a large code base, I wholeheartedly agree with your sentiment and would welcome a standardized version of this.  Just as std::unique_ptr and std::shared_ptr explicitly document their semantics, so too does observer_ptr, therefore making the code clearer to readers, users, and maintainers.  Large code bases are always maintained by more than one person, and unless everyone agrees on the meaning of T* there can be confusion, subtle errors, and maintenance problems.  The idea of an observer_ptr class avoids that and enables legacy code to be transformed at will.

If it would be helpful, I would be happy to contribute anything from my own incarnation of an observer_ptr.  Perhaps merging ideas would ensure that the API handles use cases well.

Something that you did not mention that I have found useful is a make_observer() function for construction.  This is mostly useful to explicitly construct an observer when that helps code clarity.

Given the increased clarity and decreased ambiguity I have seen in my code when using this (isn’t that ultimately the goal of the STL and other designed libraries?), I have always wondered about the antipathy this idea faces, so I hope your proposal makes better progress.

Cheers,
Brook


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Joseph Thomson
On Wed, Feb 1, 2017 at 11:07 PM, Brook Milligan <[hidden email]> wrote:

>
> > On Feb 1, 2017, at 12:47 AM, Joseph Thomson <[hidden email]>
> wrote:
> >
> > The `observer_ptr<T>` class template is a pointer-like type that does not
> > do any resource management, and is intended to be used in place of `T*`
> > wherever `T*` is used as a non-owning reference to an object of type `T`.
> > `observer_ptr<T>` has three main advantages over `T*`:
>
> From my own experience, which includes writing my own version of exactly
> what you are describing and using it extensively in a large code base, I
> wholeheartedly agree with your sentiment and would welcome a standardized
> version of this.  Just as std::unique_ptr and std::shared_ptr explicitly
> document their semantics, so too does observer_ptr, therefore making the
> code clearer to readers, users, and maintainers.  Large code bases are
> always maintained by more than one person, and unless everyone agrees on
> the meaning of T* there can be confusion, subtle errors, and maintenance
> problems.  The idea of an observer_ptr class avoids that and enables legacy
> code to be transformed at will.
>

Exactly. I have heard it suggested that once all other uses are covered by
high-level types, the only use case left for `T*` is as a non-owning
pointer. Even ignoring the real safety benefits a well-designed "observer"
type brings, this idea is flawed because:

   1. This is just a convention; no one is forced to follow it.
   2. Even if everyone did follow it, legacy code will still use `T*` for
   other purposes.
   3. Even if all legacy code were updated, low level code still uses `T*`
   for other purposes.

If it would be helpful, I would be happy to contribute anything from my own
> incarnation of an observer_ptr.  Perhaps merging ideas would ensure that
> the API handles use cases well.
>

While I was just floating the idea and a review process has not officially
started, I would be happy to hear any ideas you have. Have you seen my
implementation that I linked to in my OP?

Something that you did not mention that I have found useful is a
> make_observer() function for construction.  This is mostly useful to
> explicitly construct an observer when that helps code clarity.
>

My messages are moderated as I am a new subscriber to the list, so they may
not have gone through yet, but I have mentioned that I have a
`make_observer` function. If people feel that implicit conversion from `T&`
is bad, it could even be the primary way to construct an `observer`.

Given the increased clarity and decreased ambiguity I have seen in my code
> when using this (isn’t that ultimately the goal of the STL and other
> designed libraries?), I have always wondered about the antipathy this idea
> faces, so I hope your proposal makes better progress.
>

Indeed. I was surprised when I found out the C++ standards committee was so
hostile to the idea. I'm glad that people seem receptive to the idea here.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Edward Diener-3
In reply to this post by Joseph Thomson
On 1/31/2017 11:47 PM, Joseph Thomson wrote:

> For some time, I have been developing a pair of non-owning pointer-like
> types that I am currently calling `observer_ptr` and `observer`. I had
> planned to propose their addition to the C++ standard library, but I have
> been informed by the author of the original `observer_ptr` proposal
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282.pdf> that
> the ISO C++ committee has rejected his proposal and made clear that it
> feels there is no place in the standard library for such types, believing
> that this role is filled to a satisfactory degree by regular pointers. I
> wholeheartedly disagree with this assessment, so I am bringing my proposal
> here instead.
>
> The `observer_ptr<T>` class template is a pointer-like type that does not
> do any resource management, and is intended to be used in place of `T*`
> wherever `T*` is used as a non-owning reference to an object of type `T`.

When referring to 'T*' I think you should always use the terminology
'pointer' rather than 'reference'. By mixing the two you are confusing
terminology, which I believe should always be distinct because a pointer
and a reference are syntactically two different things in C++.

snipped...




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Niall Douglas
In reply to this post by Joseph Thomson
On 01/02/2017 07:47, Joseph Thomson wrote:

> For some time, I have been developing a pair of non-owning pointer-like
> types that I am currently calling `observer_ptr` and `observer`. I had
> planned to propose their addition to the C++ standard library, but I have
> been informed by the author of the original `observer_ptr` proposal
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282.pdf> that
> the ISO C++ committee has rejected his proposal and made clear that it
> feels there is no place in the standard library for such types, believing
> that this role is filled to a satisfactory degree by regular pointers. I
> wholeheartedly disagree with this assessment, so I am bringing my proposal
> here instead.

I don't think that exactly accurate. Rather it is that the GSL's
proposed schema of:

* owner<T> is an owning pointer
* span<T> is a borrowed pointer/reference/view
* C type pointers are non-owning, non-borrowed

... has general wide agreement in principle, if not in exact
formulation. The Library Fundamentals TS v2 does have an observer_ptr in
std::experimental, but there is general lack of sureness as to what it
actually contributes when a non-annotated pointer according to the GSL
schema is either an observer by definition, or unupgraded code.

I'd need a fair bit of convincing that observer<T> has merit in any form
except additional clarity to help demarcate unupgraded code from
upgraded code. If that's your argument, and you're not doing funny
things with implicit conversion from T& and other funny non-GSL
semantics, I'd suppose this though I'd suggest you actually contribute
it to GSL itself and persuade Neil to let it in.

The GSL is a *much* better home for it than Boost because then you'll
have Bjarne batting for it, plus static checking support from Microsoft
in VS2017 and Google via clang-tidy. You'll also get a *huge* userbase
almost instantly, because the GSL or rather one of its C++ 98 clones is
seeing exponential growth recently. It's amazingly useful for upgrading
ancient C++ codebases.

Niall

--
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Richard Hodges
In reply to this post by Edward Diener-3
There is already an observer_ptr proposed for c++17.

http://en.cppreference.com/w/cpp/experimental/observer_ptr


On 1 February 2017 at 17:22, Edward Diener <[hidden email]> wrote:

> On 1/31/2017 11:47 PM, Joseph Thomson wrote:
>
>> For some time, I have been developing a pair of non-owning pointer-like
>> types that I am currently calling `observer_ptr` and `observer`. I had
>> planned to propose their addition to the C++ standard library, but I have
>> been informed by the author of the original `observer_ptr` proposal
>> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282.pdf> that
>> the ISO C++ committee has rejected his proposal and made clear that it
>> feels there is no place in the standard library for such types, believing
>> that this role is filled to a satisfactory degree by regular pointers. I
>> wholeheartedly disagree with this assessment, so I am bringing my proposal
>> here instead.
>>
>> The `observer_ptr<T>` class template is a pointer-like type that does not
>> do any resource management, and is intended to be used in place of `T*`
>> wherever `T*` is used as a non-owning reference to an object of type `T`.
>>
>
> When referring to 'T*' I think you should always use the terminology
> 'pointer' rather than 'reference'. By mixing the two you are confusing
> terminology, which I believe should always be distinct because a pointer
> and a reference are syntactically two different things in C++.
>
> snipped...
>
>
>
>
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman
> /listinfo.cgi/boost
>

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Joseph Thomson
In reply to this post by Niall Douglas
On Thu, Feb 2, 2017 at 6:18 AM, Niall Douglas <[hidden email]>
wrote:

> On 01/02/2017 07:47, Joseph Thomson wrote:
> > For some time, I have been developing a pair of non-owning pointer-like
> > types that I am currently calling `observer_ptr` and `observer`. I had
> > planned to propose their addition to the C++ standard library, but I have
> > been informed by the author of the original `observer_ptr` proposal
> > <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282.pdf> that
> > the ISO C++ committee has rejected his proposal and made clear that it
> > feels there is no place in the standard library for such types, believing
> > that this role is filled to a satisfactory degree by regular pointers. I
> > wholeheartedly disagree with this assessment, so I am bringing my
> proposal
> > here instead.
>
> I don't think that exactly accurate. Rather it is that the GSL's
> proposed schema of:
>
> * owner<T> is an owning pointer
> * span<T> is a borrowed pointer/reference/view
> * C type pointers are non-owning, non-borrowed
>

As far as I understand it, `span<T>` is a view of objects over a range, in
the vein of `array_view<T>`, and raw pointers are simply non-owning. I'm
not sure what "borrowed" means in this context.

... has general wide agreement in principle, if not in exact
> formulation. The Library Fundamentals TS v2 does have an observer_ptr in
> std::experimental, but there is general lack of sureness as to what it
> actually contributes when a non-annotated pointer according to the GSL
> schema is either an observer by definition, or unupgraded code.
>

That is just one of the benefits I listed (documentation of intent). The
most benefit important IMO is *type-safety*, followed closely by a more
minimal interface. The `observer_ptr<T>` in `std::experimental` only has
type safety in one direction (conversion to `T*` is explicit), because the
only way to construct it is from `T*`. Observers should preferably be
constructed from `T&`, as this is a type-safe conversion. The
`observer_ptr<T>` in `std::experimental` needs one change to make it type
safe: change `make_observer(T*)` to `make_observer(T&)`.

In my opinion, designating `T*` to mean "observer" would be okay in an
ideal world (it still has far too general an interface for something that
just observes), but the world isn't ideal. Not everyone reads the GSL
guidelines, and those who do won't follow it to the letter, and even if
they did there is still plenty of "unupgraded" code. Also, I think you too
easily dismiss the benefit of being able to distinguish between un-upgraded
and upgraded code; this sounds very useful if you ask me. So, to reiterate
again, `observer_ptr`:

   - Allows upgraded code to be distinguished from un-upgraded code (this
   is more important than you might think)
   - Removes operations that are inappropriate for an observer type
   (pointer arithmetic, array subscript, conversion to `void*`)
   - Provides type safety by allowing construction from `T&` and
   disallowing construction from and conversion to `T*`

Whether to allow implicit/explicit conversion from `T&` is a design detail.
The benefits are there regardless.

Also, it seems to me that the natural meaning of `T*` in C++ is as an
iterator, not an observer:

int arr[] = { 1, 2, 3 };
auto it = std::end(arr); // `decltype(it)` is `int*`

I'd need a fair bit of convincing that observer<T> has merit in any form
> except additional clarity to help demarcate unupgraded code from
> upgraded code. If that's your argument, and you're not doing funny
> things with implicit conversion from T& and other funny non-GSL
> semantics, I'd suppose this though I'd suggest you actually contribute
> it to GSL itself and persuade Neil to let it in.
>

`observer<T>` is similar to `not_null<T>`, in that it enforces a "not null"
precondition, except `observer<T>` does a much better job because it
enforces the precondition at compile-time.

auto o = make_observer(null_ptr); // compile error: expects `T&`
auto n = not_null<T*>(null_ptr); // compiles fine; run-time error

`observer` forces the user to dereference their pointer, which should be
flagged as unsafe by the static analyser if they don't check for null.
`not_null` waits until compile-time to report the error, and makes it
harder for a static analyser to catch the potential null pointer bug.

I have had a few discussions with Neil over at the GSL GitHub page about
the purpose of `not_null`. Honestly, the design goals of `not_null<T>` seem
unclear to me; it seems to be trying to do too many things at once,
simultaneously trying to be a drop-in replacement for `T*` that enforces a
"not null" precondition at run-time (it's meant to be able to hold any kind
of pointer or pointer-like object), but also trying to be this high-level
modern type that has compile-time type safety (it deletes various pointer
arithmetic operations, and it has been seriously suggested that conversion
from `T` should be explicit). It was initially meant to be compatible with
smart pointers like `unique_ptr`, but this goal seems to have been all but
abandoned after it was realised that this won't really work. It's also
meant to be used in conjunction with strings, despite the fact that
`string_view` is a much better alternative, and with the `owner`
annotation, despite the fact that this will probably have the same
conceptual problems as `unique_ptr`. If my ramblings sound confused, it's
because I am confused, because `not_null` is confused.

The GSL is a *much* better home for it than Boost because then you'll
> have Bjarne batting for it, plus static checking support from Microsoft
> in VS2017 and Google via clang-tidy. You'll also get a *huge* userbase
> almost instantly, because the GSL or rather one of its C++ 98 clones is
> seeing exponential growth recently. It's amazingly useful for upgrading
> ancient C++ codebases.
>

This would be good. If I brought this to the GSL, I would pretty much be
proposing that `not_null` is scrapped in favour of `observer` and
`observer_ptr`. `not_null<zstring>` is obsoleted by `string_view`;
`not_null<unique_ptr<T>>` etc. are broken; `not_null<owner<T>>` is of
little value IMO, and may be conceptually broken too; honestly, the only
useful case is `not_null<T*>`, and that currently has big issues with its
design too. `observer` and `observer_ptr` are essentially `maybe_null` and
`not_null` with clearer design goals and a fixed interface.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Vicente Botet
In reply to this post by Joseph Thomson
Le 01/02/2017 à 08:47, Joseph Thomson a écrit :
Hi,

thanks for bringing these classes to boost ML discussion.

> For some time, I have been developing a pair of non-owning pointer-like
> types that I am currently calling `observer_ptr` and `observer`.
I don't think observer and observer_ptr are the good names. Both are
pointers as they have pointer semantics.
I'll suggest not_null_ptr and observer_ptr

> I had
> planned to propose their addition to the C++ standard library, but I have
> been informed by the author of the original `observer_ptr` proposal
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282.pdf> that
> the ISO C++ committee has rejected his proposal and made clear that it
> feels there is no place in the standard library for such types, believing
> that this role is filled to a satisfactory degree by regular pointers. I
> wholeheartedly disagree with this assessment, so I am bringing my proposal
> here instead.

I'm confused. observed_ptr is part of the C++ Fundamental TS v2. Why do
you say that it was rejected?

> The `observer_ptr<T>` class template is a pointer-like type that does not
> do any resource management, and is intended to be used in place of `T*`
> wherever `T*` is used as a non-owning reference to an object of type `T`.
> `observer_ptr<T>` has three main advantages over `T*`:
>
>     1. `T&` is implicitly convertible to `observer_ptr<T>` which, unlike `T*`,
>     makes it *type-safe*. `T*` can represent things that are not
>     conceptually objects of type `T`: arrays, strings, iterators. No
>     implicit conversion from `T*` means that these things cannot implicitly
>     convert to `observer_ptr<T>`. Pointers aren't even required to point to
>     valid objects (e.g. a past-the-end iterator). Conversely, in a well-formed
>     program, `T&` is *always* a valid object of type `T`.
>     2. `observer_ptr<T>` documents its purpose. This is really a side-effect
>     of it being type-safe (a type should have a single, specific purpose), but
>     it's worth mentioning. Conversely, when you see `T*`, it may not be
>     immediately obvious what it represents.
>     3. `observer_ptr<T>` has a minimal interface, which makes it harder to
>     misuse than `T*`; for example, `observer_ptr<T>` has no pointer
>     arithmetic operators, no array subscript operator, no conversion to
>     `void*`.
So you have added the implicit conversion from T& to the FTSV2 observed_ptr.
Why implicit?
You have added mixed comparisons, between observed_ptr<T1> and T2. Have
you added them because the conversion was implicit?
Could you show a concrete and real a use case?
>
> The `observer<T>` class template is a counterpart to `observer_ptr<T>` that
> has *no null state*; it cannot be default constructed, constructed from
> `nullptr_t` or constructed from `T*`, and it does not contextually convert
> to `bool`. The only way to create an `observer<T>` is from `T&`. This
> allows a "not null" precondition to be enforced at compile-time, rather
> than having to worry about pointers being null at run-time.
Wondering if an explicit conversion from T*, requiring that T* is not
nullptr is not useful. This is C++.
When the user knows that the pointer is not null, it seams natural that
the user can construct an observer<T>

if (T* ptr = f())
     g(observer<T>(ptr));

observer<T>(ptr) will be UB if ptr is equal to nullptr.

Or are you suggesting that the user de-reference the pointer to get a
reference
if (T* ptr = f())
     g(observer<T>(*ptr);

or with a factory

if (T* ptr = f())
     g(not_null(ptr);


I believe it is worth proposing the not-null observer pointer to the C++
standard.
And why not the construction from T& for observer_ptr<T>.

I don't share the get_pointer concern. smart pointer have a get function .
However I believe it is worth proposing an explicit conversion in
addition to the get function

Vicente



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Vicente Botet
In reply to this post by Joseph Thomson
Le 02/02/2017 à 02:15, Joseph Thomson a écrit :

> On Thu, Feb 2, 2017 at 6:18 AM, Niall Douglas <[hidden email]>
> wrote:
>
>> On 01/02/2017 07:47, Joseph Thomson wrote:
>>> For some time, I have been developing a pair of non-owning pointer-like
>>> types that I am currently calling `observer_ptr` and `observer`. I had
>>> planned to propose their addition to the C++ standard library, but I have
>>> been informed by the author of the original `observer_ptr` proposal
>>> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4282.pdf> that
>>> the ISO C++ committee has rejected his proposal and made clear that it
>>> feels there is no place in the standard library for such types, believing
>>> that this role is filled to a satisfactory degree by regular pointers. I
>>> wholeheartedly disagree with this assessment, so I am bringing my
>> proposal
>>> here instead.
>> I don't think that exactly accurate. Rather it is that the GSL's
>> proposed schema of:
>>
>> * owner<T> is an owning pointer
>> * span<T> is a borrowed pointer/reference/view
>> * C type pointers are non-owning, non-borrowed
>>
> As far as I understand it, `span<T>` is a view of objects over a range, in
> the vein of `array_view<T>`, and raw pointers are simply non-owning. I'm
> not sure what "borrowed" means in this context.
>
> ... has general wide agreement in principle, if not in exact
>> formulation. The Library Fundamentals TS v2 does have an observer_ptr in
>> std::experimental, but there is general lack of sureness as to what it
>> actually contributes when a non-annotated pointer according to the GSL
>> schema is either an observer by definition, or unupgraded code.
>>
> That is just one of the benefits I listed (documentation of intent). The
> most benefit important IMO is *type-safety*, followed closely by a more
> minimal interface. The `observer_ptr<T>` in `std::experimental` only has
> type safety in one direction (conversion to `T*` is explicit), because the
> only way to construct it is from `T*`. Observers should preferably be
> constructed from `T&`, as this is a type-safe conversion. The
> `observer_ptr<T>` in `std::experimental` needs one change to make it type
> safe: change `make_observer(T*)` to `make_observer(T&)`.
We need a proposal to change experimental::observer_ptr :)

>
> In my opinion, designating `T*` to mean "observer" would be okay in an
> ideal world (it still has far too general an interface for something that
> just observes), but the world isn't ideal. Not everyone reads the GSL
> guidelines, and those who do won't follow it to the letter, and even if
> they did there is still plenty of "unupgraded" code. Also, I think you too
> easily dismiss the benefit of being able to distinguish between un-upgraded
> and upgraded code; this sounds very useful if you ask me. So, to reiterate
> again, `observer_ptr`:
>
>     - Allows upgraded code to be distinguished from un-upgraded code (this
>     is more important than you might think)
>     - Removes operations that are inappropriate for an observer type
>     (pointer arithmetic, array subscript, conversion to `void*`)
>     - Provides type safety by allowing construction from `T&` and
>     disallowing construction from and conversion to `T*`
I agree we need this vocabulary type. GSL guidelines are for code that
will be written from scratch with C++14/C++17.
The reality is that we have tons of C++98 code. Pretending that T* is a
not owning pointer because we have gsl::owner is not useful in a legacy
code project. I'm not saying that gsl::owner is not useful.
> Whether to allow implicit/explicit conversion from `T&` is a design detail.
> The benefits are there regardless.
Yes, I believe the implicit conversion could be questionable.

>
> Also, it seems to me that the natural meaning of `T*` in C++ is as an
> iterator, not an observer:
>
> int arr[] = { 1, 2, 3 };
> auto it = std::end(arr); // `decltype(it)` is `int*`
>
> I'd need a fair bit of convincing that observer<T> has merit in any form
>> except additional clarity to help demarcate unupgraded code from
>> upgraded code. If that's your argument, and you're not doing funny
>> things with implicit conversion from T& and other funny non-GSL
>> semantics, I'd suppose this though I'd suggest you actually contribute
>> it to GSL itself and persuade Neil to let it in.
>>
> `observer<T>` is similar to `not_null<T>`, in that it enforces a "not null"
> precondition, except `observer<T>` does a much better job because it
> enforces the precondition at compile-time.
>
> auto o = make_observer(null_ptr); // compile error: expects `T&`
> auto n = not_null<T*>(null_ptr); // compiles fine; run-time error
I prefer also a not null smart pointer that takes this as a
precondition. Requiring the class to check the parameter is not nullptr
(as gsl::not_null does) is more than what I need.

> `observer` forces the user to dereference their pointer, which should be
> flagged as unsafe by the static analyser if they don't check for null.
> `not_null` waits until compile-time to report the error, and makes it
> harder for a static analyser to catch the potential null pointer bug.
>
> I have had a few discussions with Neil over at the GSL GitHub page about
> the purpose of `not_null`. Honestly, the design goals of `not_null<T>` seem
> unclear to me; it seems to be trying to do too many things at once,
> simultaneously trying to be a drop-in replacement for `T*` that enforces a
> "not null" precondition at run-time (it's meant to be able to hold any kind
> of pointer or pointer-like object), but also trying to be this high-level
> modern type that has compile-time type safety (it deletes various pointer
> arithmetic operations, and it has been seriously suggested that conversion
> from `T` should be explicit). It was initially meant to be compatible with
> smart pointers like `unique_ptr`, but this goal seems to have been all but
> abandoned after it was realised that this won't really work. It's also
> meant to be used in conjunction with strings, despite the fact that
> `string_view` is a much better alternative, and with the `owner`
> annotation, despite the fact that this will probably have the same
> conceptual problems as `unique_ptr`. If my ramblings sound confused, it's
> because I am confused, because `not_null` is confused.
Maybe we could have not_null<Ptr> that works for any pointer-like type,
but what I need today is not_null_ptr<T>.
Maybe it is worth providing a single not_null<T*> instantiation.

>
> The GSL is a *much* better home for it than Boost because then you'll
>> have Bjarne batting for it, plus static checking support from Microsoft
>> in VS2017 and Google via clang-tidy. You'll also get a *huge* userbase
>> almost instantly, because the GSL or rather one of its C++ 98 clones is
>> seeing exponential growth recently. It's amazingly useful for upgrading
>> ancient C++ codebases.
>>
> This would be good. If I brought this to the GSL, I would pretty much be
> proposing that `not_null` is scrapped in favour of `observer` and
> `observer_ptr`. `not_null<zstring>` is obsoleted by `string_view`;
> `not_null<unique_ptr<T>>` etc. are broken; `not_null<owner<T>>` is of
> little value IMO, and may be conceptually broken too; honestly, the only
> useful case is `not_null<T*>`, and that currently has big issues with its
> design too. `observer` and `observer_ptr` are essentially `maybe_null` and
> `not_null` with clearer design goals and a fixed interface.
>
>
>
In reverse order ;-)

Vicente


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Joseph Thomson
In reply to this post by Vicente Botet
I don't think observer and observer_ptr are the good names. Both are
pointers as they have pointer semantics.
I'll suggest not_null_ptr and observer_ptr


I consider both to be pointer-like types because they implement `operator*`
and have reference (pointer-like) semantics. But `observer` is not default
constructible, constructible from `T*` or `nullptr_t`, and is not
contextually convertible to `bool`. I chose the name `observer` because it
conveys intent (to observe something), and I felt it was appropriate to
append `_ptr` to the type that is constructible from a pointer (because
thus has a null state). The types are inherently similar, so I feel they
should have similar names.

I dislike the name `not_null_ptr` because it conveys no intent (there is
more than one use for a non-owning pointer to a single object), and because
it makes it seem completely unrelated to `observer_ptr`.

I'm confused. observed_ptr is part of the C++ Fundamental TS v2. Why do you
say that it was rejected?


I was informed by the author of the proposal that the committee had made it
clear that they were not interested in an "observer" pointer in any form.
Perhaps this is not accurate, as someone else on this thread suggested.

So you have added the implicit conversion from T& to the FTSV2 observed_ptr.
Why implicit?
You have added mixed comparisons, between observed_ptr<T1> and T2. Have you
added them because the conversion was implicit?
Could you show a concrete and real a use case?


I added this because I believed it to be reasonable. The reason is that it
discourages the use of raw pointer, which is not conceptually type safe and
can be error prone. However, after someone pointed out that implicit
conversion from `T&` makes the intentions of the function taking an
`observer_ptr` unclear, I feel that it might be safer to make the
conversion explicit. `make_observer` would be the standard way to construct
an `observer`, essentially replacing the `&` operator in this context.

Mixed comparisons naturally follow from implicit conversions, but they
would be removed if the conversions were made explicit.

Wondering if an explicit conversion from T*, requiring that T* is not
nullptr is not useful. This is C++.
When the user knows that the pointer is not null, it seams natural that the
user can construct an observer<T>

if (T* ptr = f())
    g(observer<T>(ptr));

observer<T>(ptr) will be UB if ptr is equal to nullptr.

Or are you suggesting that the user de-reference the pointer to get a
reference
if (T* ptr = f())
    g(observer<T>(*ptr);

or with a factory

if (T* ptr = f())
    g(not_null(ptr);


The entire point of `observer` is to avoid making assumptions, and to have
the type system enforce preconditions at compile-time. By allowing
construction from `T*`, the compile-time type-safety of `observer` is lost.
This is one of the major issues I have with `gsl::not_null` (though it has
many other problems).

And yes, the user has to dereference a pointer to convert it to an
`observer`. It is commonly understood that dereferencing a null pointer is
UB, and this can be tested for with static analysis tools. There is no need
to design more UB into types that are supposed to be more high-level and
type-safe than the C-style options (e.g. pointers).

I believe it is worth proposing the not-null observer pointer to the C++
standard.
And why not the construction from T& for observer_ptr<T>.


I have three options for my proposal, all recommended as the best avenue by
different people: the C++ standard, Boost, and the GSL. I'm not sure which
one to persue. I'm glad you think that the idea is worth proposing though :)

I don't share the get_pointer concern. smart pointer have a get function .
However I believe it is worth proposing an explicit conversion in addition
to the get function


`get_pointer` is a relatively minor design detail that isn't fundamental to
the proposal. I wouldn't be devastated by a `get` member function.

Thanks for taking the time to look at everything in detail!

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Joseph Thomson
In reply to this post by Vicente Botet
We need a proposal to change experimental::observer_ptr :)
>

That was my intention before I was informed by the proposal author that the
proposal was a dead-end. I am not sure whether it would or would not be
worth pursuing now.

I agree we need this vocabulary type. GSL guidelines are for code that will
be written from scratch with C++14/C++17.
The reality is that we have tons of C++98 code. Pretending that T* is a not
owning pointer because we have gsl::owner is not useful in a legacy code
project. I'm not saying that gsl::owner is not useful.


Totally agree. In addition, there is still more than one use for `T*` in
the Core Guidelines (observer and "optional reference" parameter). I would
rather look at some unfamiliar code and see `observer_ptr<T>` than see `T*`
and have to consider whether or not the code is adhering to the guidelines.
The guidelines also assume that all people follow the guidelines perfectly,
and that the static analysis can catch all the "incorrect" uses of `T*`,
and that all code has been upgraded. In my opinion, `observer` and
`observer_ptr` embody the guidelines' own rules to "be type-safe" and
"express intent".


Whether to allow implicit/explicit conversion from `T&` is a design detail.
> The benefits are there regardless.
>
Yes, I believe the implicit conversion could be questionable.


Yes. I am increasingly feeling this way.

`observer<T>` is similar to `not_null<T>`, in that it enforces a "not null"
> precondition, except `observer<T>` does a much better job because it
> enforces the precondition at compile-time.
>
> auto o = make_observer(null_ptr); // compile error: expects `T&`
> auto n = not_null<T*>(null_ptr); // compiles fine; run-time error
>
I prefer also a not null smart pointer that takes this as a precondition.
Requiring the class to check the parameter is not nullptr (as gsl::not_null
does) is more than what I need.


Disagree. As I said, better to enforce at compile-time using the type
system.


`observer` forces the user to dereference their pointer, which should be

> flagged as unsafe by the static analyser if they don't check for null.
> `not_null` waits until compile-time to report the error, and makes it
> harder for a static analyser to catch the potential null pointer bug.
>
> I have had a few discussions with Neil over at the GSL GitHub page about
> the purpose of `not_null`. Honestly, the design goals of `not_null<T>` seem
> unclear to me; it seems to be trying to do too many things at once,
> simultaneously trying to be a drop-in replacement for `T*` that enforces a
> "not null" precondition at run-time (it's meant to be able to hold any kind
> of pointer or pointer-like object), but also trying to be this high-level
> modern type that has compile-time type safety (it deletes various pointer
> arithmetic operations, and it has been seriously suggested that conversion
> from `T` should be explicit). It was initially meant to be compatible with
> smart pointers like `unique_ptr`, but this goal seems to have been all but
> abandoned after it was realised that this won't really work. It's also
> meant to be used in conjunction with strings, despite the fact that
> `string_view` is a much better alternative, and with the `owner`
> annotation, despite the fact that this will probably have the same
> conceptual problems as `unique_ptr`. If my ramblings sound confused, it's
> because I am confused, because `not_null` is confused.
>
Maybe we could have not_null<Ptr> that works for any pointer-like type, but
what I need today is not_null_ptr<T>.
Maybe it is worth providing a single not_null<T*> instantiation.


I believe that `not_null` could be useful as a transparent pointer type
that can be used to enforce the "not null" precondition at compile-time
where you have a legacy interface that you do not want to break by updating
your interface to use some other kind of modern type (e.g. `observer` or
`vector` or whatever). I believe it should do nothing other than prevent
the pointer from becoming null (e.g. it should support pointer arithmetic).

In other words, `not_null` should be a crutch for legacy code that cannot
be updated to use modern C++ facilities because it would break client code.
Other, modern, type-safe facilities should be recommended for new C++ code.

`observer` and `observer_ptr` are essentially `maybe_null` and
> `not_null` with clearer design goals and a fixed interface.
>
> In reverse order ;-)


Yeah, I noticed that after I pressed send :)

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Is there any interest in non-owning pointer-like types?

Joseph Thomson
I agree we need this vocabulary type. GSL guidelines are for code that will
be written from scratch with C++14/C++17.
The reality is that we have tons of C++98 code. Pretending that T* is a not
owning pointer because we have gsl::owner is not useful in a legacy code
project. I'm not saying that gsl::owner is not useful.


Sorry, one additional comment. AFAIK, the GSL is aimed at those writing new
C++ code, those updating old C++ code, and those making low-level C++ code
safer. For example, `owner` is for use where something like `unique_ptr`
cannot be used (either legacy code, or perhaps the library implementation
of `unique_ptr` itself!)

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
12