On 4/15/20 11:36 PM, Alf P. Steinbach wrote:
> On 16.04.2020 04:40, James Kuyper wrote:
>> On Wednesday, April 15, 2020 at 9:44:31 PM UTC-4, Alf P. Steinbach wrote:
>>> On 15.04.2020 23:03, James Kuyper wrote:
...
>>>> Could you explain that a little more? Specifically, could you give an
>>>> example of how it could cause problems?
You've responded to me twice now, and still have not provided an
example. Source code demonstrating the problem you're worried about
would make your point much clearer than any amount of words could -
particular since it's become quite clear that we aren't communicating
with each other very well using words.
>>>> I've worked with C/C++ for 40 years now. In both of those languages, the
>>>> integral promotions (in C, they're called integer promotions) apply to
>>>> any integer type with an integer conversion rank less than that of int
>>>> for which all of it's values can be represented as an 'int'. That is
>>>> guaranteed to be true of signed char, and short. On most common systems
>>>> today, they also apply to char, unsigned char, unsigned short,
>>>> [u]int8_t, and [u]int16_t, [u]int_least8_t, [u]int_least16_t,
>>>> [u]int_fast8_t, and [u]intfast16_t. I've used systems where 'int' is a
>>>> 64-bit type, on which [u]int32_t, [u]int_least32_t and [u]int_fast32_t
>>>> are also subject to promotion. And while those promotions do
>>>> occasionally cause problems, they're very far from being the biggest,
>>>> most common, or most difficult to deal with problems I run into.
>>>>
>>>> One key reason why they tend to be unproblematic is that the integral
>>>> promotions, as a matter of deliberate design, never change the value of
>>>> an expression, only it's type.
>>>
>>> The purpose of an `operator""i16` is to control the type.
>>>
>>> So with all those words you're ignoring the main aspect.
>>>
>>> Since you ask for an example, `foo( -42i16 )` can do the entirely wrong
>>> (unintended) thing, for example if foo copies a value into a memory area
>>> representing a file header, and advances a write position.
>>
>> Yes, but that's nothing new. Given
>>
>> constexpr int16_t negfortytwo = -42;
Sorry - I muddied the waters by incorporating the '-' into that
definition. The parallels are clearer in the code below, which handles
that differently.
>> negfortytwo has a type that is very well-defined, but despite
>> that fact, you'll have exactly the same problems with negfortytwo
>> that you would with -42i16.
>
> No. You fail to understand that if `foo` depends on the type of the
> argument, then it depends on the type of the argument.
Note: according to n4659.pdf "Literal suffix identifiers (16.5.8) that
do not start with an underscore are reserved for future
standardization." (20.5.4.3.5). I found this out while testing the code
below, which wouldn't compile until I changed i16 to _i16.
#include <iostream>
#include <typeinfo>
int16_t operator"" _i16(unsigned long long x) {
return x;
}
constexpr int16_t fortytwo_16 = 42;
template<class T> void foo(T t) {
std::cout << typeid(t).name() << ":" << t << "\n";
}
int main(void)
{
foo(fortytwo_16);
foo(42_i16);
foo(-fortytwo_16);
foo(-42_i16);
return 0;
}
~/Programming/C++/testprog(61) ~/Programming/C++/testprog(60) g++
-std=c++1y -pedantic -Wall -Wpointer-arith -Wcast-align
-fno-enforce-eh-specs -ffor-scope -fno-gnu-keywords
-fno-nonansi-builtins -Wctor-dtor-privacy -Wnon-virtual-dtor
-Wold-style-cast -Woverloaded-virtual -Wsign-promo literal.cpp -o literal
~/Programming/C++/testprog(62) literal
s:42
s:42
i:-42
i:-42
Yes, foo does depend upon the type of the argument. And the integral
promotions triggered by the use of unary '-' do change the type. But
that's just as much of a problem with -42_i16 as it is with -fortytwo_16.
>> It might be annoying that the ability
>> to specify user-defined literals doesn't solve this problem, but
>> its not a disaster, it's something that every experienced C or
>> C++ programmer has been dealing with for as long as they've been
>> using those languages.
>
> No, they haven't. It gives the impression that you have very little
> experience. I know that to be probably false, so it's baffling.
I've been dealing with the problem shown by my code above for more than
30 years now, and it's not particularly difficult to do so. It predates
int16_t - the same problem comes up with "short" and "signed char". It
predates C++ - C has the same rule, though they are now called "integer
promotions" rather than "integral promotions". If that rule causes some
different kind of problem for user-defined literals, you've yet to
articulate what that problem is.
The clearest way to show the problems you're worrying about would be to
show me some code where -42_i16 causes a problem, but replacing it with
-fortytwo_16 does not.
>>> It could even be that foo is so badly designed that it does slightly
>>> different but conceptually similar things for `int` and `int16_t`. I
>>> recently had experience with the FLTK GUI library, used in Bjarne's
>>> intro book, and it does slightly different things for `double` versus
>>> `int` coordinates in graphics, e.g. whether it involves transformation.
>>> When one deals with libraries like that controlling the type is key.
>>
>> The integral promotions never result in a floating point type.
>
> That's an irrelevant observation.
You've complained about a problem supposedly caused by integral
promotions, and in the same context, a library that does different
things with integral and floating point arguments. If the fact that
integral promotions never result in a floating point type is irrelevant
to the second part of that complaint, then pray please explain the
connection that you do see between your previous complaint and this one.
...
>> It would be more of a surprise, at least to experienced
>> programmers, if the integral promotions don't occur just because
>> user defined literals are involved. It would be slightly less
>> confusing if the integer promotions were simply removed
>> completely, rather than setting up a special exemption from them
>> for user define integer literals.
>
> Rather than special-casing the existing rules, as you seem to imagine, a
> better design of user-defined literals would have removed the dependency
> on a language feature (the sign operators) that renders many expressions
> meaningless.
The use of user-defined literals is dependent on the integral promotions
entirely because the operator""() overloads are allowed to return
integral types that are smaller than int. The only way to remove that
dependency without special casing for user-defined literals would be to
prohibit them from returning integer types that are smaller than int.
And that would count as special-casing on the return type.
It would be far easier for me to have some idea what in the world you're
talking about if you would please identify specific clauses in the
standard that you think should be changed, and specify how they should
be changed. Please provide that actual new wording, not just a
description of the wording.