This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD Editorial status.
873. signed integral type and unsigned integral type are not clearly definedSection: 6.9.2 [basic.fundamental] Status: NAD Editorial Submitter: Travis Vitek Opened: 2008-06-30 Last modified: 2016-01-28
Priority: Not Prioritized
View all issues with NAD Editorial status.
Discussion:
Neither the term "signed integral type" nor the term "unsigned integral type" is defined in the core language section of the standard, therefore the library section should avoid its use. The terms signed integer type and unsigned integer type are indeed defined (in 6.9.2 [basic.fundamental]), thus the usages should be replaced accordingly.
Note that the key issue here is that "signed" + "integral type" != "signed integral type". The types bool
, char
, char16_t
, char32_t
and wchar_t
are all listed as integral types, but are neither of signed integer type or unsigned integer type. According to 6.9 [basic.types] p7, a synonym for integral type is integer type. Given this, one may choose to assume that an integral type that can represent values less than zero is a signed integral type. Unfortunately this can cause ambiguities. As an example, if T
is unsigned char
, the expression make_signed<T>::type
, is supposed to name a signed integral type. There are potentially two types that satisfy this requirement, namely signed char
and char
(assuming CHAR_MIN < 0
).
[ San Francisco: ]
Plum, Sebor to review.
[ Post Summit Daniel adds: ]
The proposed resolution needs to be "conceptualized". Currently we have in [concept.support] only concept
IntegralType
for all "integral types", thus indeed the currentContainer
concept and Iterator concepts are sufficiently satisfied with "integral types". If the changes are applied, we might ask core for conceptBilateralIntegerType
and add proper restrictions to the library concepts.
Proposed resolution:
I propose to use the terms "signed integer type" and "unsigned integer type" in place of "signed integral type" and "unsigned integral type" to eliminate such ambiguities.
The proposed change makes it absolutely clear that the difference between two pointers cannot be char
or wchar_t
, but could be any of the signed integer types. 7.6.6 [expr.add] paragraph 6...
- When two pointers to elements of the same array object are subtracted, the result is the difference of the subscripts of the two array elements. The type of the result is an implementation-defined signed integral type signed integer type; this type shall be the same type that is defined as
std::ptrdiff_t
in the<cstdint>
header (18.1)...
The proposed change makes it clear that X::size_type
and X::difference_type
cannot be char
or wchar_t
, but could be one of the signed or unsigned integer types as appropriate. 16.4.4.6 [allocator.requirements] table 40...
Table 40: Allocator requirements
expression return type assertion/note/pre/post-conditionX::size_type
unsigned integral type unsigned integer type a type that can represent the size of the largest object in the allocation model.X::difference_type
signed integral type signed integer type a type that can represent the difference between any two pointers in the allocation model.
The proposed change makes it clear that make_signed<T>::type
must be one of the signed integer types as defined in 3.9.1. Ditto for make_unsigned<T>type
and unsigned integer types. 21.3.9.4 [meta.trans.sign] table 48...
Table 48: Sign modifications
Template Commentstemplate <class T> struct make_signed;
IfT
names a (possibly cv-qualified) signed integral type signed integer type (3.9.1) then the member typedeftype
shall name the typeT
; otherwise, ifT
names a (possibly cv-qualified) unsigned integral type unsigned integer type thentype
shall name the corresponding signed integral type signed integer type, with the same cv-qualifiers asT
; otherwise,type
shall name the signed integral type signed integer type with the smallest rank (4.13) for whichsizeof(T) == sizeof(type)
, with the same cv-qualifiers asT
. Requires:T
shall be a (possibly cv-qualified) integral type or enumeration but not abool
type.template <class T> struct make_unsigned;
IfT
names a (possibly cv-qualified) unsigned integral type unsigned integer type (3.9.1) then the member typedeftype
shall name the typeT
; otherwise, ifT
names a (possibly cv-qualified) signed integral type signed integer type thentype
shall name the corresponding unsigned integral type unsigned integer type, with the same cv-qualifiers asT
; otherwise,type
shall name the unsigned integral type unsigned integer type with the smallest rank (4.13) for whichsizeof(T) == sizeof(type)
, with the same cv-qualifiers asT
. Requires:T
shall be a (possibly cv-qualified) integral type or enumeration but not abool
type.
Note: I believe that the basefield values should probably be prefixed with ios_base::
as they are in 28.3.4.3.3.3 [facet.num.put.virtuals] The listed virtuals are all overloaded on signed and unsigned integer types, the new wording just maintains consistency. 28.3.4.3.2.3 [facet.num.get.virtuals] table 78...
Table 78: Integer Conversions
Statestdio
equivalentbasefield == oct
%o
basefield == hex
%X
basefield == 0
%i
signed integral type signed integer type%d
unsigned integral type unsigned integer type%u
Rationale is same as above. 28.3.4.3.3.3 [facet.num.put.virtuals] table 80...
Table 80: Integer Conversions
Statestdio
equivalentbasefield == ios_base::oct
%o
(basefield == ios_base::hex) && !uppercase
%x
(basefield == ios_base::hex)
%X
basefield == 0
%i
for a signed integral type signed integer type%d
for a unsigned integral type unsigned integer type%u
23.2 [container.requirements] table 80...
Table 89: Container requirements
expression return type operational semantics assertion/note/pre/post-condition complexityX::difference_type
signed integral type signed integer type is identical to the difference type ofX::iterator
andX::const_iterator
compile timeX::size_type
unsigned integral type unsigned integer typesize_type
can represent any non-negative value ofdifference_type
compile time
24.3.4 [iterator.concepts] paragraph 1...
Iterators are a generalization of pointers that allow a C++ program to work with different data structures (containers) in a uniform manner. To be able to construct template algorithms that work correctly and efficiently on different types of data structures, the library formalizes not just the interfaces but also the semantics and complexity assumptions of iterators. All input iterators
i
support the expression*i
, resulting in a value of some class, enumeration, or built-in typeT
, called the value type of the iterator. All output iterators support the expression*i = o
whereo
is a value of some type that is in the set of types that are writable to the particular iterator type ofi
. All iteratorsi
for which the expression(*i).m
is well-defined, support the expressioni->m
with the same semantics as(*i).m
. For every iterator typeX
for which equality is defined, there is a corresponding signed integral type signed integer type called the difference type of the iterator.
I'm a little unsure of this change. Previously this paragraph would allow instantiations of linear_congruential_engine
on char
, wchar_t
, bool
, and other types. The new wording prohibits this. 29.5.4.2 [rand.eng.lcong] paragraph 2...
The template parameter
UIntType
shall denote an unsigned integral type unsigned integer type large enough to store values as large asm - 1
. If the template parameterm
is 0, the modulusm
used throughout this section 26.4.3.1 isnumeric_limits<result_type>::max()
plus 1. [Note: The result need not be representable as a value of typeresult_type
. --end note] Otherwise, the following relations shall hold:a < m
andc < m
.
Same rationale as the previous change. 99 [rand.adapt.xor] paragraph 6...
Both
Engine1::result_type
andEngine2::result_type
shall denote (possibly different) unsigned integral types unsigned integer types. The member result_type shall denote either the type Engine1::result_type or the type Engine2::result_type, whichever provides the most storage according to clause 3.9.1.
29.5.8.1 [rand.util.seedseq] paragraph 7...
Requires:
RandomAccessIterator
shall meet the requirements of a random access iterator (24.1.5) such thatiterator_traits<RandomAccessIterator>::value_type
shall denote an unsigned integral type unsigned integer type capable of accomodating 32-bit quantities.
By making this change, integral types that happen to have a signed representation, but are not signed integer types, would no longer be required to use a two's complement representation. This may go against the original intent, and should be reviewed. 32.5.8.2 [atomics.types.operations] paragraph 24...
Remark: For signed integral types signed integer types, arithmetic is defined using two's complement representation. There are no undefined results. For address types, the result may be an undefined address, but the operations otherwise have no undefined behavior.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4