Reading
http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0298r3.pdf
they say:
<quote>
Motivation and Scope
Many programs require byte-oriented access to memory.
Yes, byte access to memory has been the standard in harware since ages.
It predates C++, the term byte was coined by Werner Buchholz in July
1956. OK? Since then, a certain sequence of bits make a unit of
addressing in byte oriented machines, that since ages are standardized
as a sequence of 8 bits. Nowhere is specified what these people think
about that "many programs". Not ALL of them?
I mean all programs in C and C++ are using that access each day in
almost all computers running today. The sizeof() unit is a byte. The C
and the C++ languages are byte oriented languages.
<quote>
Today, such programs must use either the char, signed char, or unsigned
char types for this purpose.
<end quote>
Yes, I always try to use unsigned char for text, signed chars when I
store (eventually) small numbers in a byte. A signed byte can also
contain quantities like age, that with some effort could arrive at 128,
but....
I disgress.
What is important is that the existing language already gives you all
possible tools for doing all kinds of operations on unsigned chars.
They go on:
<quote>
However, these types perform a “triple duty”. Not only are they used for
byte addressing,
<end quote>
??? what has addressing to do with it?
We are speaking of bits, i.e. values.
<quote>
but also as arithmetic types,
<end quote>
yes, you can do unsigned integer operations with unsigned chars. So what?
<quote>
and as character types.
<end quote>
Yes. You can even store letters in an unsigned chars. All this is
already possible with known syntax and known rules.
<quote>
This multiplicity of roles opens the door for programmer error – such as
accidentally performing arithmetic on memory that should be treated as a
byte value – and confusion for both programmers and tools.
<end quote>
No data is provided in the document to prove this assertion. No research
is mentioned about what tools are confused and why should we bear yet
another syntax rule.
The new proposed syntax needs a template definition:
namespace std {
template <class IntegerType> // constrained appropriately
IntegerType to_integer(byte b);
}
This is doing what now is done with... nothing if you program according
to existing rules about common conversions.
unsigned char a,b;
int c;
c = a+b;
The operations are done using integer operations. This is the normal way
of doing this stuff. Now what does this template bring in new features?
They say:
<quote>
As its underlying type is unsigned char, to facilitate bit twiddling
operations, convenience conversion operations are provided for mapping a
byte to an unsigned integer type value. They are provided through the
function template.
<end quote>
But we HAVE already rules to do that. But why keep it simple when we can
complexify things?
Now, suppose that I write the following C program (that also compiles as
a C++ program)
1 #include <stdio.h>
2
3 int add(unsigned char a,unsigned char b)
4 {
5
6 for (int i=0; i != b; i = - ~i) {
7 a = - ~a;
8 }
9 return a;
10 }
11
12 int main(void)
13 {
14 unsigned char a = 3;
15 unsigned char b = 2;
16
17 printf("%d %d %d %d %d\n",a,~a,-~a,~-~a,-~-~a);
18 int c = add(a,b);
19 printf("2+3=%d\n",add(a,b));
20 printf("12+55=%d\n",add(12,55));
21 }
I am doing an addition using only logical operators because addition in
binary is based in boolean operations in the actual gates of the
hardware. Of course that is not a hardware binary adder but shows that
there is no real distinction between arithmetic operations and logical
operations in real computers.
Is this complexity warranted?
What does this bring?
namespace std {
// IntType would be constrained to be true for is_integral_v<IntType>
template <class IntType>
constexpr byte& operator<<=(byte& b, IntType shift) noexcept; template
<class IntType>
constexpr byte operator<<(byte b, IntType shift) noexcept; template
<class IntType>
constexpr byte& operator>>=(byte& b, IntType shift) noexcept;
template <class IntType>
constexpr byte operator>>(byte b, IntType shift) noexcept;
constexpr byte operator|(byte l, byte r) noexcept;
constexpr byte& operator|=(byte& l, byte r) noexcept;
constexpr byte operator&(byte l, byte r) noexcept;
constexpr byte& operator&=(byte& l, byte r) noexcept;
constexpr byte operator~(byte b) noexcept;
constexpr byte operator^(byte l, byte r) noexcept;
constexpr byte& operator^=(byte& l, byte r) noexcept;
}
All this stuff does exactly what unsigned char does...
And I can substitute unsigned char by "byte" in the program above and it
should work isn't it?