Why is std::atomic<T*> lacking T* operator -> ?

1,495 views
Skip to first unread message

C. Schreiber

unread,
Jul 13, 2012, 8:10:12 AM7/13/12
to std-dis...@isocpp.org
Hi,

Since there is already a specialization of std::atomic for pointer types, it would be both easy and convenient to define an operator -> so that one can access the fields of the pointed object as usual, i.e. pointer->field, instead of being forced to use the verbose (*pointer).field notation (see for example the article of H. Sutter: http://www.drdobbs.com/parallel/writing-lock-free-code-a-corrected-queue/210604448).

As I see it, although it is not an atomic operation if one considers both the pointer *and* the pointed object, it is atomic for the pointer alone: only one read is made, and it can be made atomic just like operator * is. Hence, adding this operator would not break the implicit contract of std::atomic that it provides atomic operations on its wrapped value (that is, only the pointer, not the pointed object).

So is there any particular reason not to define this operator?

Best regards,
C. Schreiber.

Lawrence Crowl

unread,
Jul 24, 2012, 4:48:38 PM7/24/12
to std-dis...@isocpp.org
Whether or not one adds this operator is debatable. The core of
the problem is "convenience that leads to error". In this case, it
would be very convenient to have code like "a->x + a->y", but that
code likely has a bug because a may change between the two loads.
The solution, in this case, would be to not support ->. However,
that same logic also applies to "*". We could as well not have that
and require .load(). It is a judgement call based in large part
on where one minimizes complaints. Extending the set of operators
allowed in a later standard is relatively easy, restricting them
is not.

--
Lawrence Crowl

C. Schreiber

unread,
Jul 24, 2012, 6:29:15 PM7/24/12
to std-dis...@isocpp.org
On Tuesday, July 24, 2012 10:48:38 PM UTC+2, Lawrence Crowl wrote:
Whether or not one adds this operator is debatable.  The core of
the problem is "convenience that leads to error".  In this case, it
would be very convenient to have code like "a->x + a->y", but that
code likely has a bug because a may change between the two loads.
The solution, in this case, would be to not support ->.  However,
that same logic also applies to "*".  We could as well not have that
and require .load().  It is a judgement call based in large part
on where one minimizes complaints.  Extending the set of operators
allowed in a later standard is relatively easy, restricting them
is not.
 
I understand your point.

But to get back to your example: for T not a pointer type, std::atomic<T> has an operator T() which allows one to write things like "a + a". This, in the very same way, is also likely to be a bug, but is perfectly allowed by the current standard. Given that, I feel that the absence of operator -> is somehow inconsistent with the rest of the interface of std::atomic, which seems to let you use std::atomic<T/T*> as an rvalue just like a T/T*.

I'd say that either allowing it fully (i.e. adding the -> operator) or restricting access via the .load() function are two good solutions. But the current situation sits in between, and I think it can be confusing at first sight.

Lawrence Crowl

unread,
Jul 25, 2012, 12:11:34 AM7/25/12
to std-dis...@isocpp.org
I think you are not the only one with that view. Personally, I can live with
either extreme or the middle. I would not object to a change allowing ->.

--
Lawrence Crowl
Reply all
Reply to author
Forward
0 new messages