Tuesday, January 4, 2022

Digest for comp.lang.c++@googlegroups.com - 25 updates in 3 topics

Manfred <noname@add.invalid>: Jan 04 12:56AM +0100

On 1/3/2022 11:24 PM, Andrey Tarasevich wrote:
> http://coliru.stacked-crooked.com/a/3f8c3e96cd39f596
 
> In C++17 the user-defined comparison operator is used. In C++20
> conversion to `int` and subsequent comparison of `int`s is used.
 
That's really odd indeed.
Are you sure that is is the C++20 standard that mandates this behavior?
I wouldn't be surprised if this were a plain bug in the implementation -
possibly related with the changes that you mention above - but still a bug.
 
In fact, gcc 11.2 with plain -std=c++20 gives '01':
 
https://www.godbolt.org/z/rEjfehdnY
Manfred <noname@add.invalid>: Jan 04 12:59AM +0100

On 1/4/2022 12:56 AM, Manfred wrote:
> possibly related with the changes that you mention above - but still a bug.
 
> In fact, gcc 11.2 with plain -std=c++20 gives '01':
 
> https://www.godbolt.org/z/rEjfehdnY
 
scratch that last bit (for some reason godbolt uses diferent comiler
selections fro compilation and program output)
 
https://www.godbolt.org/z/be1q7PErE
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jan 04 12:23AM

On Mon, 3 Jan 2022 14:13:15 -0800
 
> Before C++20 the conversion to `const char *` is not used and everything
> is perfectly defined here. There's no "undefined behavior" of any kind
> in C++17 semantics of this code.
 
Ah yes, I misread your code. You are not comparing pointers, you are
comparing indeterminate values. I would need to look it up but my
recollection is that reading (and so comparing) an uninitialized value
also comprises undefined behaviour, unless it is of unsigned char or
std::byte type. Here you seem to be comparing an uninitialized int and
char (via S:: operator <) type.
Andrey Tarasevich <andreytarasevich@hotmail.com>: Jan 03 04:33PM -0800

On 1/3/2022 4:23 PM, Chris Vine wrote:
> also comprises undefined behaviour, unless it is of unsigned char or
> std::byte type. Here you seem to be comparing an uninitialized int and
> char (via S:: operator <) type.
 
No. That is incorrect. All values involved in these comparisons are
perfectly initialized.
 
Both `std::pair` objects are initialized with their default
constructors, which in turn perform value-initialization of their
members. In my example all `std::pair`s fields are guaranteed to be
initialized to zero. Nothing indeterminate here.
 
--
Best regards,
Andrey Tarasevich .
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jan 04 12:39AM

On Tue, 4 Jan 2022 00:23:24 +0000
> also comprises undefined behaviour, unless it is of unsigned char or
> std::byte type. Here you seem to be comparing an uninitialized int and
> char (via S:: operator <) type.
 
Actually I think they should be initialized because of the brace
initializer. I don't use C++ very much any more so I may be wrong
about that; but if so there is surely something odd about this. It
looks like a bug.
Andrey Tarasevich <andreytarasevich@hotmail.com>: Jan 03 04:59PM -0800

On 1/3/2022 3:56 PM, Manfred wrote:
> Are you sure that is is the C++20 standard that mandates this behavior?
> I wouldn't be surprised if this were a plain bug in the implementation -
> possibly related with the changes that you mention above - but still a bug.
 
I'm not yet that good with the intricacies of the implicitly generated
comparators, but I see the dilemma the compiler is facing here. It is either
 
1. user-provided measly `<`-only comparison directly on `S`, or
 
2. implicit conversion that leads from `S` to `int` with strong
full-blown `<=>` comparison.
 
The compiler apparently opts for the latter.
 
I can see the attraction of the latter path, but the fact that it
quietly defeats a used-defined comparator looks scary. Granted, it
doesn't defeat it directly, since `std::pair`s comparator serves as an
intermediary, but still...
 
Once we declare the conversion operator as `explicit`, the phenomenon
expectedly disappears and C++20 falls back to the "traditional" behavior.
 
--
Best regards,
Andrey Tarasevich
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jan 04 01:27AM

On Mon, 3 Jan 2022 16:59:25 -0800
Andrey Tarasevich <andreytarasevich@hotmail.com> wrote:
[snip]
> intermediary, but still...
 
> Once we declare the conversion operator as `explicit`, the phenomenon
> expectedly disappears and C++20 falls back to the "traditional" behavior.
 
Frankly, this is unacceptable for an industry standard language such as
C++. I was disappointed with some of the breaking changes in C++17
(one bizarre outcome of which was that std::uninitialized_copy, and the
other std::unitialized_* functions, gave rise to undefined behaviour
according to other parts of the same standard), but this one from C++20
to which you refer is I think worse because it causes breaking compiler
behaviour in real life.
 
C++ is not my first choice for new projects nowadays, although it still
has some uses.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 03 06:51PM -0800

On 1/3/2022 9:48 AM, Andrey Tarasevich wrote:
> use the user-defined `<` and also output `00`.
 
> The above results were obtained with GCC. Clang 10 outputs `00` even in
> `-std=c++20` mode, but Clang 11 and later output `01`.
 
Bugger!
Juha Nieminen <nospam@thanks.invalid>: Jan 04 08:27AM

> constructors, which in turn perform value-initialization of their
> members. In my example all `std::pair`s fields are guaranteed to be
> initialized to zero. Nothing indeterminate here.
 
Are you sure "default-initialization = zero-initialization" is guaranteed
for POD objects?
 
The default initialization of 'char' (as all the other primitive types) is
"don't initialize". Is this different if the 'char' is a member of a POD
object that has no explicit constructor?
wij <wyniijj@gmail.com>: Jan 04 03:53AM -0800

On Tuesday, 4 January 2022 at 01:49:09 UTC+8, Andrey Tarasevich wrote:
 
> --
> Best regards,
> Andrey Tarasevich
 
// file t.cpp
#include <iostream>
 
struct S
{
char c;
 
operator const char *() const { return &c; }
 
friend bool operator <(const S& lhs, const S& rhs)
{
std::cout << 'c' ;
return lhs.c < rhs.c; }
};
 
int main()
{
std::pair<int, S> p1{}, p2{};
std::cout << (p1 < p2) << (p2 < p1) << std::endl;
}
----
 
[]$ g++ t.cpp -std=c++20
[]$ ./a.out
01
[]$ g++ t.cpp -std=c++17
[]$ ./a.out
c0c0
 
---
Problem was verified.
It looked to me an overloading issue with std::pair.
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Jan 04 05:24PM +0100

On 4 Jan 2022 09:27, Juha Nieminen wrote:
 
> The default initialization of 'char' (as all the other primitive types) is
> "don't initialize". Is this different if the 'char' is a member of a POD
> object that has no explicit constructor?
 
Value initialization was about the only new feature in C++03, which was
otherwise just Technical Corrigendum 1. It was invented by Andrew Koenig.
 
The point of value initialization was to guarantee initialization of
everything, if anything in an object was initialized (e.g., an object
with a `std::string` and a `double` should not end up with the `string`
initialized and the `double` indeterminate, as it could in C++98).
 
For that purpose value initialization, used by the `std::pair` default
constructor, ends up zero-initializing those things not otherwise
initialized.
 
 
- Alf
Andrey Tarasevich <andreytarasevich@hotmail.com>: Jan 04 10:26AM -0800

On 1/4/2022 12:27 AM, Juha Nieminen wrote:
 
> The default initialization of 'char' (as all the other primitive types) is
> "don't initialize". Is this different if the 'char' is a member of a POD
> object that has no explicit constructor?
 
`std::pair` is a not a POD type (if you insist on using outdated
terminology). It has a user-provided constructor.
 
In my example the top-level initialization is performed by the default
constructor of `std::pair`, which is guaranteed (by specification of
`std::pair`) to invoke *value-initialization* of both members.
 
Value-initialization of `char` (and other scalar types) is
zero-initialization.
 
Even if `std::pair` were a POD, the explicitly specified `{}`
initializer in my example would still trigger value-initialization of
the entire `std::pair`, which would in turn lead to value-initialization
of both members.
 
--
Best regards,
Andrey Tarasevich
"Öö Tiib" <ootiib@hot.ee>: Jan 04 02:49PM -0800

On Tuesday, 4 January 2022 at 02:59:43 UTC+2, Andrey Tarasevich wrote:
> intermediary, but still...
 
> Once we declare the conversion operator as `explicit`, the phenomenon
> expectedly disappears and C++20 falls back to the "traditional" behavior.
 
I so far thought that <=> only breaks the philosophy of not
paying for what we don't use (implementation of < is often
cheaper than <=>, operator != is almost always cheaper).
Thanks for showing that it is far worse. :(
 
That it somehow manages to compose the <=> when you
make operator int() explicit is also odd ... I think all the
comparison operators of std::pair were removed
by C++20 and replaced with alien flying vessel operator.
"Öö Tiib" <ootiib@hot.ee>: Jan 03 11:50PM -0800

On Tuesday, 4 January 2022 at 00:15:10 UTC+2, Manfred wrote:
> mean different things.
 
> The irony is that this is probably one of those examples where C beats
> C++ - good ol' HUGE_VALF or INFINITE would raise no question at all!
 
The std::numeric_limits<float>::infinity() does not raise questions
in actual programs either. It is infinity of float, very explicitly.
Issues of BM with it are pseudo-issues. Too lot of characters?
WTF? Did the hard drive get full? Name some local constant
like "beyond_horizon" or something. Next BM needs to output it to
json as number and then what? Runs away crying?
Juha Nieminen <nospam@thanks.invalid>: Jan 04 07:58AM

> {
> static int i = 123;
> };
 
As you probably know, 'static' variables declared inside a class aren't
actually member variables, but free-floating variables which visibility
scope is inside that class (the term "class variable" is often used for
these types of variables, in many OO languages, as opposed to "member
variable").
 
The 'static int i;' in the class definition is just a declaration, and
it needs to be actually defined, ie. instantiated somewhere, in one
(and only one) compilation unit. If you don't instantiate it somewhere
the compiler will be unable to decide where to instantiate it and you'll
get a linker error because it has only been declared but not instantiated
in any compilation unit.
 
C++17 extended the 'inline' functionality, which does that automatically
for you (so that you don't have to instantiate the variable by hand),
but prior to it you had to do it yourself.
 
I suppose that when C++98 was standardized it was decided that it's
better to specify the initial value of that 'static' variable where
it's instantiated rather than where it's declared. (I suppose that
technically speaking it wouldn't be hard for compilers to look up
the initial value from either one, because to instantiate the variable
it needs to see the declaration.) Perhaps it was thought that it causes
less confusion because if it's initialized in the declaration it may
look like it will be initialized to that value every time the class
is instantiated (which, of course, is not the case).
 
> in the same way that const members are initialised? I've never seen a good
> reason why it must be this way and it makes for messy header files.
 
I don't think const member variables can be initialized in the class
definition in C++98. That syntax was only introduced in C++11.
Juha Nieminen <nospam@thanks.invalid>: Jan 04 08:34AM

> The irony is that this is probably one of those examples where C beats
> C++ - good ol' HUGE_VALF or INFINITE would raise no question at all!
 
What is the type of INFINITE? What if you want it as one of the other two
floating point types? (Is casting defined in this case?)
Muttley@dastardlyhq.com: Jan 04 09:15AM

On Mon, 03 Jan 2022 17:40:28 GMT
>due to duplicate definitions of the static variable when the class
>definition is include by multiple compilation units. Hence the requirement
>to declare it in a single compilation unit.
 
C++ hasn't been translated into C for 25 years at least. Keeping this syntatic
quirk for so long rather demonstrates the C++ committee are more interested in
adding shiny shiny "fun" stuff to the language that they find interesting
rather than improving it for normal developers.
Muttley@dastardlyhq.com: Jan 04 09:17AM

On Tue, 4 Jan 2022 07:58:41 -0000 (UTC)
 
>I suppose that when C++98 was standardized it was decided that it's
>better to specify the initial value of that 'static' variable where
>it's instantiated rather than where it's declared. (I suppose that
 
I'd love to see their reasoning for that.
 
>technically speaking it wouldn't be hard for compilers to look up
 
It wouldn't be hard at all.
 
>less confusion because if it's initialized in the declaration it may
>look like it will be initialized to that value every time the class
>is instantiated (which, of course, is not the case).
 
If someone was new to C++ perhaps, otherwise no.
 
>I don't think const member variables can be initialized in the class
>definition in C++98. That syntax was only introduced in C++11.
 
Quite possibly.
Manfred <noname@add.invalid>: Jan 04 10:42AM +0100

On 1/4/2022 8:50 AM, Öö Tiib wrote:
>> C++ - good ol' HUGE_VALF or INFINITE would raise no question at all!
 
> The std::numeric_limits<float>::infinity() does not raise questions
> in actual programs either. It is infinity of float, very explicitly.
No, I'm talking about these questions about 'static', 'const',
'constexpr' and similar entertainment. In C INFINITE and HUGE_VAL are
"constant expressions", and that is it - good for any purpose.
 
Manfred <noname@add.invalid>: Jan 04 10:47AM +0100

On 1/4/2022 9:34 AM, Juha Nieminen wrote:
>> C++ - good ol' HUGE_VALF or INFINITE would raise no question at all!
 
> What is the type of INFINITE? What if you want it as one of the other two
> floating point types? (Is casting defined in this case?)
 
"The macro INFINITY expands to a constant expression of type float
representing positive or unsigned infinity"
It can't be any clearer than that.
I believe there are automatic conversions to double and long double.
Others can confirm and give the exact reference for this part.
 
HUGE_VAL comes in all variants for different types, from float to double
to decimal.
scott@slp53.sl.home (Scott Lurndal): Jan 04 03:24PM

>quirk for so long rather demonstrates the C++ committee are more interested in
>adding shiny shiny "fun" stuff to the language that they find interesting
>rather than improving it for normal developers.
 
Of course, they did "fix" it - in a backward compatible way - in C++17, right?
Muttley@dastardlyhq.com: Jan 04 04:06PM

On Tue, 04 Jan 2022 15:24:06 GMT
>>adding shiny shiny "fun" stuff to the language that they find interesting
>>rather than improving it for normal developers.
 
>Of course, they did "fix" it - in a backward compatible way - in C++17, right?
 
How exactly do you have backwards compatible new syntax?
 
And waiting until 2017 to (sort of) fix a rather basic syntatic fault doesn't
exactly suggest they have their finger on the pulse of C++ devs. But we knew
that anyway.
"Öö Tiib" <ootiib@hot.ee>: Jan 04 10:15AM -0800

On Tuesday, 4 January 2022 at 11:43:12 UTC+2, Manfred wrote:
> No, I'm talking about these questions about 'static', 'const',
> 'constexpr' and similar entertainment. In C INFINITE and HUGE_VAL are
> "constant expressions", and that is it - good for any purpose.
 
Then I'm lost ... std::numeric_limits<float>::infinity() IS constant expression
and that is it, good for any purpose.
 
Manfred <noname@invalid.add>: Jan 04 08:49PM +0100

On 1/4/22 7:15 PM, Öö Tiib wrote:
>> "constant expressions", and that is it - good for any purpose.
 
> Then I'm lost ... std::numeric_limits<float>::infinity() IS constant expression
> and that is it, good for any purpose.
 
I'll try and lend you a compass:
 
Manfred wrote:
> static constexpr float inf = std::numeric_limits<float>::infinity();
> }
 
> /* use my::inf wherever you like */
 
The reason for it was to try and please C++ purists (we're in c.l.c++
after all), and get a compact representation of INF - I can see the
issue with using std::numeric_limits<float>::infinity() embedded in some
application expression, which serves totally different purposes than
inspecting the details of numeric representation of the implementation.
 
So, suppose you want compact, but you don't like <math.h>, the above is
an answer - note that obviously you want my::inf to be a constant
expression. Also, you want it local (as you say below), and along
similar lines I made it 'static', to make it clear - even if 'constexpr'
defaults to it.
 
BUT, then people started whirling around the use of 'static' in
combination with 'const' and 'constexpr' and all that fuzz - again, good
ol' C wouldn't do that - you'd just use INFINITY or one of the HUGE_VAL
variants, and be done with it.
 
 
love problem <lovepro416@gmail.com>: Jan 04 03:55AM -0800

The problems with religion can be a source of confusion, particularly in love quotes. People who are religious might feel that they are incompatible, and their beliefs may not always be compatible with those of their partner. This can cause misunderstandings, which can be frustrating. But, love can override these problems if the relationship is healthy. If you are a member of a particular religion, you can still enjoy the many benefits of relationships based on your faith.
 
The first problem with religion is that it's based on faith. It's an outdated notion that doesn't reflect the world or the human experience. It also assumes that a person's belief system is true. This, of course, is a fallacy. And that's not to say that falling in love with someone who doesn't share your faith is impossible. Regardless of your background, there is no reason why you can't fall in a romantic relationship.
 
Another issue with religion is that it assumes that the other person shares the same religious beliefs. This isn't true. There is no such thing as absolute love. And this is the biggest problem with religion. Most people, including Christians, believe that God is the essence of love. In the New Testament, we find the phrase, "God is love," twice. Thankfully, this expression does not imply a conflict of faith.
 
 
https://www.love-problem.solutions/baba-ji/
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: