Wednesday, July 22, 2020

Digest for comp.lang.c++@googlegroups.com - 12 updates in 2 topics

"Öö Tiib" <ootiib@hot.ee>: Jul 21 11:54PM -0700

On Wednesday, 22 July 2020 01:10:16 UTC+3, Frederick Gotham wrote:
> if the enum is not anonymous then I think there is a way of determining if it contains a particular member.
 
I assume you mean enumerator by "member" or "value"?
There are no way to enumerate defined enumerators of enum. Several
enumerators may have same value.
As of values of enum variable all values that are valid values of
underlying integral type of said enum are valid values of the
enum too. Going out of bounds is undefined behavior.
 
> I think this would be similar to determining whether a class has a particular member data or member function.
 
Counting and enumerating data members programmatically is perhaps
only possible for aggregate structs. For non-aggregates it
is impossible without external parser tool.
 
> I think this is what the 'has_' functions are for in Boost, but I cannot understand the documentation.
 
Lot of reflection and meta-programming tricks that are possible
are used in boost. Still the result is that under limited
circumstances we get something. We don't have reflection
in C++ unless we program it ourselves into or around our types.
Juha Nieminen <nospam@thanks.invalid>: Jul 22 07:14AM

> are used in boost. Still the result is that under limited
> circumstances we get something. We don't have reflection
> in C++ unless we program it ourselves into or around our types.
 
I'm wondering if you are using the correct term there.
 
According to wikipedia (which as we all know is the supreme authority in
everything) introspection means the ability to examine the type or properties
of an object, while reflection means, in addition, the ability to
manipulate these properties.
 
It's not immediately clear what it means by that, but I get the impression
that it means, essentially, that with introspection you can check, for
example, if an object has a member function with a given name/signature,
while with reflection you can also *call* that function if it exists
(ie. you won't get a compiler error if it doesn't actually exist, as long
as you don't call it if it doesn't).
 
Of course all this is from the perspective of runtime
introspection/reflection. The distinction may become a bit fuzzier at
compile time.
"Öö Tiib" <ootiib@hot.ee>: Jul 22 02:52AM -0700

On Wednesday, 22 July 2020 10:14:49 UTC+3, Juha Nieminen wrote:
> > circumstances we get something. We don't have reflection
> > in C++ unless we program it ourselves into or around our types.
 
> I'm wondering if you are using the correct term there.
 
I meant "reflection" in meaning of program's capability
to meta-analyse and meta-program itself.
 
> while with reflection you can also *call* that function if it exists
> (ie. you won't get a compiler error if it doesn't actually exist, as long
> as you don't call it if it doesn't).
 
For me capability to inspect properties of data types (introspection) is
a part of program's capability to meta-analyse itself. So in that view
introspection is sub-feature of sub-feature of reflection.
 
> Of course all this is from the perspective of runtime
> introspection/reflection. The distinction may become a bit fuzzier at
> compile time.
 
Oh indeed it is fuzzy since the definitions of terms how different
people use those overlap in big part but rarely match perfectly.
For example for me reflection includes introspection fully while
for others there can be almost dichotomy between those. :D
 
C++ program can do very lot of processing compile time, big part of
what it is even disallowed to do run-time. For me compile-time
meta-programming is also sub-feature of sub-feature of reflection.
 
In my experience other programming languages tend to be far weaker
in that sector of reflection and in my experience boost is using
majority of tricks of it that C++ provides ... nice or ugly.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 22 04:15PM +0200

On 22.07.2020 08:54, Öö Tiib wrote:
> As of values of enum variable all values that are valid values of
> underlying integral type of said enum are valid values of the
> enum too. Going out of bounds is undefined behavior.
 
If by "out of bounds" you mean outside the range of minimum to maximum
enumerator value, then happily no UB any longer. C++17 fixed that.
Because `std::byte`.
 
 
[snip]
 
- Alf
"Öö Tiib" <ootiib@hot.ee>: Jul 22 07:53AM -0700

On Wednesday, 22 July 2020 17:15:54 UTC+3, Alf P. Steinbach wrote:
 
> If by "out of bounds" you mean outside the range of minimum to maximum
> enumerator value, then happily no UB any longer. C++17 fixed that.
> Because `std::byte`.
 
But how? C++17 itself added borken std::byte into language. C++20 is
supposed to fix it. C++20 being officially published is still being
underway (maybe thanks to pandemic?).
From C++20 it will be modular arithmetic for unsigned underlying
types and UB for signed underlying types.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jul 22 10:19PM +0200

On 22.07.2020 16:53, Öö Tiib wrote:
> underway (maybe thanks to pandemic?).
> From C++20 it will be modular arithmetic for unsigned underlying
> types and UB for signed underlying types.
 
First, it appears I was wrong, I remembered this incorrectly. :-(
 
And I got it backwards: it's C++17 that is the most unreliable with UB,
while C++14 and earlier just had unspecified.
 
Not sure where I got the notion that the introduction of std::byte
encountered the problem so they had to fix it.
 
The problem with exceeding the range of the defined enumerator values is
for converting to enum type without fixed underlying type. Enum types
with fixed underlying type don't have the problem.
 
In the standard the two different rules are abstracted up as a single
rule with the differences baked into the notion of "enumeration values"
which for an enum with unspecified underlying type are the values of a
bit field just large enough to contain the enumerator values, but which
for an enum with fixed underlying types are the underlying type values...
 
Essentially, for this purpose the underlying type of an enum with
unspecified underlying type is assumed to be a minimum bit field.
 
C++14 §5.2.9/10:
"A value of integral or enumeration type can be explicitly converted to
an enumeration type. The value is unchanged if the original value is
within the range of the enumeration values (7.2). Otherwise, the
resulting value is unspecified (and might not be in that range)."
 
C++17 §8.2.9/10:
"A value of integral or enumeration type can be explicitly converted to
a complete enumeration type. The value is unchanged if the original
value is within the range of the enumeration values (10.2). Otherwise,
the behavior is undefined."
 
 
- Alf (on his way to getting completely senile, it seems)
Frederick Gotham <cauldwell.thomas@gmail.com>: Jul 22 02:52AM -0700

Before I begin, I realise I can just use an atomic_bool but I'm intentionally not for this example.
 
bool g_is_on;
std::mutex g_mtx_is_on;
 
bool Is_On(void)
{
std::lock_guard<std::mutex> guard(g_mtx_is_on);
 
return g_is_on;
}
 
Is the above code alright? Or do I need an intermediary as so:
 
bool Is_On(void)
{
std::lock_guard<std::mutex> guard(g_mtx_is_on);
 
bool const temp = g_is_on;
 
return temp;
}
Bo Persson <bo@bo-persson.se>: Jul 22 12:37PM +0200

On 2020-07-22 at 11:52, Frederick Gotham wrote:
 
> bool const temp = g_is_on;
 
> return temp;
> }
 
The first version is fine. Any destructors are run at the very end of
the scope, after handling any return value. Otherwise returning from
local variables with destructors wouldn't work.
Bonita Montero <Bonita.Montero@gmail.com>: Jul 22 12:48PM +0200

> std::lock_guard<std::mutex> guard(g_mtx_is_on);
> return g_is_on;
> }
 
For what is this nonsense-code good for ?
"Fred. Zwarts" <F.Zwarts@KVI.nl>: Jul 22 01:14PM +0200

Op 22.jul..2020 om 11:52 schreef Frederick Gotham:
 
> bool const temp = g_is_on;
 
> return temp;
> }
 
Both versions will return the value that g_is_on after locking the
mutex. However, at the moment that the caller inspects the returned
value, g_is_on may have been changed already, because the mutex is
unlocked after determining the return value, but before the caller
proceeds with the next thing. So, in most cases, the mutex is needed in
the caller.
 
--
Paradoxes in the relation between Creator and creature.
<http://www.wirholt.nl/English>.
"Öö Tiib" <ootiib@hot.ee>: Jul 22 05:08AM -0700

On Wednesday, 22 July 2020 12:52:28 UTC+3, Frederick Gotham wrote:
 
> bool const temp = g_is_on;
 
> return temp;
> }
 
There are no observable difference between what these two examples
of functions do so compiler can generate same code for both.
Paavo Helde <eesnimi@osa.pri.ee>: Jul 22 03:32PM +0300

22.07.2020 12:52 Frederick Gotham kirjutas:
 
> return g_is_on;
> }
 
> Is the above code alright? Or do I need an intermediary as so:
 
The above is fine, return value is copied over before releasing the lock.
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: