This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.
atomic
free functions incorrectly specifiedSection: 32.5.2 [atomics.syn] Status: Resolved Submitter: Pete Becker Opened: 2011-03-01 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [atomics.syn].
View all other issues in [atomics.syn].
View all issues with Resolved status.
Discussion:
In earlier specifications of atomics the template specialization atomic<integer>
was derived from atomic_integer
(e.g. atomic<int>
was derived from atomic_int
),
and the working draft required free functions such as
int atomic_load(const atomic_int*)
for each of the atomic_integer
types. This worked fine with normal function overloading.
For the post-Batavia working draft, N3193 removed the requirement that atomic<integer>
be derived from atomic_integer
and replaced the free functions taking pointers to
atomic_integer
with template functions taking atomic_type*
, such as
template <class T> T atomic_load(const atomic_type*);
and a code comment explaining that atomic_type
can be either atomic<T>
or a
named base class of atomic<T>
. The latter possibility is supposed to allow existing
implementations based on the previous specification to continue to conform.
From history, this allowance seems to imply that functions like atomic_load
can be non-template
free functions, as they were before. The explicit requirements do not allow this, and, by requiring that
they be templates, make them far more complicated. As the specification is currently written, code that
uses an implementation that uses a base class would have to provide an explicit template type:
atomic<int> my_atomic_int; atomic_load<int>(&my_atomic_int);
That type argument isn't needed when atomic_type
is atomic<T>
, but cautious
users would always provide it to make their code portable across different implementations of the
standard library.
One possibility for the implementor would be to do some template meta-programming to infer the type
T
when there are no function parameters of type T
, but without running afoul of the
prohibition on adding parameters with default values (16.4.6.4 [global.functions]/3).
So the promise that implementations of the previous specification continue to conform has not been met. The specification of these free functions should be rewritten to support library code written to the previous specification or the vacuous promise should be removed.
[2011-03-08: Lawrence comments and drafts wording:]
One of the goals is to permit atomics code to compile under both C and C++. Adding explicit template arguments would defeat that goal.
The intent was to permit the normal function overloads foratomic_int
when atomic_int
is distinct from atomic<int>
. That intent was not reflected in the wording.
Proposed Resolution
Explicitly permit free functions.
Edit within the header
<atomic>
synopsis 32.5.2 [atomics.syn] as follows:// 29.6.1, general operations on atomic types// In the following declarations, atomic_type is either //// In the following declarations, atomic-type is either //atomic<T>
or a named base class forT
from // Table 145 or inferred from // Table 146.atomic<T>
or a named base class forT
from // Table 145 or inferred from // Table 146. // If it isatomic<T>
, then the declaration is a template // declaration prefixed withtemplate <class T>
template <class T>bool atomic_is_lock_free(const volatileatomic_typeatomic-type*);template <class T>bool atomic_is_lock_free(constatomic_typeatomic-type*);template <class T>void atomic_init(volatileatomic_typeatomic-type*, T);template <class T>void atomic_init(atomic_typeatomic-type*, T);template <class T>void atomic_store(volatileatomic_typeatomic-type*, T);template <class T>void atomic_store(atomic_typeatomic-type*, T);template <class T>void atomic_store_explicit(volatileatomic_typeatomic-type*, T, memory_order);template <class T>void atomic_store_explicit(atomic_typeatomic-type*, T, memory_order);template <class T>T atomic_load(const volatileatomic_typeatomic-type*);template <class T>T atomic_load(constatomic_typeatomic-type*);template <class T>T atomic_load_explicit(const volatileatomic_typeatomic-type*, memory_order);template <class T>T atomic_load_explicit(constatomic_typeatomic-type*, memory_order);template <class T>T atomic_exchange(volatileatomic_typeatomic-type*, T);template <class T>T atomic_exchange(atomic_typeatomic-type*, T);template <class T>T atomic_exchange_explicit(volatileatomic_typeatomic-type*, T, memory_order);template <class T>T atomic_exchange_explicit(atomic_typeatomic-type*, T, memory_order);template <class T>bool atomic_compare_exchange_weak(volatileatomic_typeatomic-type*, T*, T);template <class T>bool atomic_compare_exchange_weak(atomic_typeatomic-type*, T*, T);template <class T>bool atomic_compare_exchange_strong(volatileatomic_typeatomic-type*, T*, T);template <class T>bool atomic_compare_exchange_strong(atomic_typeatomic-type*, T*, T);template <class T>bool atomic_compare_exchange_weak_explicit(volatileatomic_typeatomic-type*, T*, T, memory_order, memory_order);template <class T>bool atomic_compare_exchange_weak_explicit(atomic_typeatomic-type*, T*, T. memory_order, memory_order);template <class T>bool atomic_compare)exchange_strong_explicit(volatileatomic_typeatomic-type*, T*, T, memory_order, memory_order);template <class T>bool atomic_compare_exchange_strong_explicit(atomic_typeatomic-type*, T*, T, memory_order, memory_order); // 29.6.2, templated operations on atomic types// In the following declarations, atomic_type is either //template <class T> T atomic_fetch_add(volatileatomic<T>
or a named base class forT
from // Table 145 or inferred from // Table 146.atomic-typeatomic<T>*, T); template <class T> T atomic_fetch_add(atomic-typeatomic<T>*, T); template <class T> T atomic_fetch_add_explicit(volatileatomic-typeatomic<T>*, T, memory_order); template <class T> T atomic_fetch_add_explicit(atomic-typeatomic<T>*, T, memory_order); template <class T> T atomic_fetch_sub(volatileatomic-typeatomic<T>*, T); template <class T> T atomic_fetch_sub(atomic-typeatomic<T>*, T); template <class T> T atomic_fetch_sub_explicit(volatileatomic-typeatomic<T>*, T, memory_order); template <class T> T atomic_fetch_sub_explicit(atomic-typeatomic<T>*, T, memory_order); template <class T> T atomic_fetch_and(volatileatomic-typeatomic<T>*, T); template <class T> T atomic_fetch_and(atomic-typeatomic<T>*, T); template <class T> T atomic_fetch_and_explicit(volatileatomic-typeatomic<T>*, T, memory_order); template <class T> T atomic_fetch_and_explicit(atomic-typeatomic<T>*, T, memory_order); template <class T> T atomic_fetch_or(volatileatomic-typeatomic<T>*, T); template <class T> T atomic_fetch_or(atomic-typeatomic<T>*, T); template <class T> T atomic_fetch_or_explicit(volatileatomic-typeatomic<T>*, T, memory_order); template <class T> T atomic_fetch_or_explicit(atomic-typeatomic<T>*, T, memory_order); template <class T> T atomic_fetch_xor(volatileatomic-typeatomic<T>*, T); template <class T> T atomic_fetch_xor(atomic-typeatomic<T>*, T); template <class T> T atomic_fetch_xor_explicit(volatileatomic-typeatomic<T>*, T, memory_order); template <class T> T atomic_fetch_xor_explicit(atomic-typeatomic<T>*, T, memory_order); // 29.6.3, arithmetic operations on atomic types // In the following declarations, atomic-integral is either //atomic<T>
or a named base class forT
from // Table 145 or inferred from // Table 146. // If it isatomic<T>
, // then the declaration is a template specialization declaration prefixed with //template <>
template <>integral atomic_fetch_add(volatile atomic-integral*, integral);template <>integral atomic_fetch_add(atomic-integral*, integral);template <>integral atomic_fetch_add_explicit(volatile atomic-integral*, integral, memory_order);template <>integral atomic_fetch_add_explicit(atomic-integral*, integral, memory_order);template <>integral atomic_fetch_sub(volatile atomic-integral*, integral);template <>integral atomic_fetch_sub(atomic-integral*, integral);template <>integral atomic_fetch_sub_explicit(volatile atomic-integral*, integral, memory_order);template <>integral atomic_fetch_sub_explicit(atomic-integral*, integral, memory_order);template <>integral atomic_fetch_and(volatile atomic-integral*, integral);template <>integral atomic_fetch_and(atomic-integral*, integral);template <>integral atomic_fetch_and_explicit(volatile atomic-integral*, integral, memory_order);template <>integral atomic_fetch_and_explicit(atomic-integral*, integral, memory_order);template <>integral atomic_fetch_or(volatile atomic-integral*, integral);template <>integral atomic_fetch_or(atomic-integral*, integral);template <>integral atomic_fetch_or_explicit(atomic-integral*, integral, memory_order);template <>integral atomic_fetch_or_explicit(atomic-integral*, integral, memory_order);template <>integral atomic_fetch_xor(volatile atomic-integral*, integral);template <>integral atomic_fetch_xor(atomic-integral*, integral);template <>integral atomic_fetch_xor_explicit(volatile atomic-integral*, integral, memory_order);template <>integral atomic_fetch_xor_explicit(atomic-integral*, integral, memory_order);Edit [atomics.types.operations.general] paragraph 1+2 as follows:
-1- The implementation shall provide the functions and function templates identified as "general operations on atomic types" in 32.5.2 [atomics.syn].
-2- In the declarations of these functions and function templates, the name atomic-type refers to eitheratomic<T>
or to a named base class forT
from Table 145 or inferred from Table 146.In [atomics.types.operations.templ] delete paragraph 2:
-1- The implementation shall declare but not define the function templates identified as "templated operations on atomic types" in 32.5.2 [atomics.syn].
-2- In the declarations of these templates, the name atomic-type refers to eitheratomic<T>
or to a named base class forT
from Table 145 or inferred from Table 146.Edit [atomics.types.operations.arith] paragraph 1+2 as follows:
-1- The implementation shall provide the functions and function template specializations identified as "arithmetic operations on atomic types" in 32.5.2 [atomics.syn].
-2- In the declarations of these functions and function template specializations, the name integral refers to an integral type and the name atomic-integral refers to eitheratomic<
integral>
or to a named base class for integral from Table 145 or inferred from Table 146.
Proposed resolution:
Resolved 2011-03 Madrid meeting by paper N3278