Thursday, February 16, 2017

Digest for comp.lang.c++@googlegroups.com - 22 updates in 8 topics

Bo Persson <bop@gmb.dk>: Feb 16 01:29AM +0100

>> };
 
> That shows a weakness of std::variant that I hadn't thought
> of -- there are no names associated with the members.
 
But there is a get<type>(v) to access a value of the selected type.
 
 
> };
 
> Or
 
> ::std::variant<uint64_t>
 
This can be the accidental result of using std::variant<types...>.
Should we forbid this when sizeof...(types) == 1?
 
 
 
Bo Persson
woodbrian77@gmail.com: Feb 15 06:08PM -0800

On Wednesday, February 15, 2017 at 6:30:16 PM UTC-6, Bo Persson wrote:
 
> > ::std::variant<uint64_t>
 
> This can be the accidental result of using std::variant<types...>.
> Should we forbid this when sizeof...(types) == 1?
 
I think so. At least the documentation should explain that
there's no good reason to use a variant<T>.
 
 
Brian
Ebenezer Enterprises - "When you like your work, every day is
a holiday." Frank Tyger
 
http://webEbenezer.net
scott@slp53.sl.home (Scott Lurndal): Feb 16 01:41PM

>compilers support it. It is usage that std::variant does
>not allow. Type-punning can be achieved with 'reinterpret_cast'
>or with 'memcpy' so union is also not needed for it.
 
Why use an extremely ugly ineffecient solution like memcpy or reinterpret_cast when the
union works just fine? And has worked just fine for forty
years. And will work fine for the forseeable future.
 
As for the uses of std::variant, they're limited to a very few
real-world applications; it's not generally useful.
scott@slp53.sl.home (Scott Lurndal): Feb 16 01:43PM


>OTOH, memcpy() is guaranteed to do the correct thing and will be most
>probably compiled to the same machine code anyway nowadays, so portable
>C++ code should use memcpy.
 
Most of my code is extremely performance intensive (cpu bound) and
littering the code with memcpy's would be silly.
 
Fundamentally, type punning with unions has worked for forty years
and will continue to work into the future, and it yields efficient
and readable code. The lack of type-safety frankly isn't an issue.
Paavo Helde <myfirstname@osa.pri.ee>: Feb 16 04:38PM +0200

On 16.02.2017 15:41, Scott Lurndal wrote:
>> or with 'memcpy' so union is also not needed for it.
 
> Why use an extremely ugly ineffecient solution like memcpy or reinterpret_cast when the
> union works just fine?
 
Ugly is in the eye of beholder and can be hidden away in a service function.
 
About inefficient: both memcpy and union get compiled into the same
machine code:
 
tmp>g++ test4.cpp -std=c++11 -O2 -Wall
tmp>./a.out f f f
Line 14
40
tmp>g++ test4.cpp -std=c++11 -O2 -Wall -DUSE_UNION
tmp>./a.out f f f
Line 24
40
tmp>g++ test4.cpp -std=c++11 -O2 -Wall -S -o n.s
tmp>g++ test4.cpp -std=c++11 -O2 -Wall -DUSE_UNION -S -o u.s
tmp>diff n.s u.s
19c19
< movl $14, %esi
---
> movl $24, %esi
51c51
< movl $14, %esi
---
> movl $24, %esi
 
IOW, the only difference is the __LINE__ constant.
 
------------------------------------------------------------------------
 
tmp>cat test4.cpp
#include <stdint.h>
#include <string.h>
#include <stdio.h>
 
struct Reg {
uint64_t base : 32;
uint64_t vmid : 16;
uint64_t reserved_48_63: 16;
};
 
#ifndef USE_UNION
 
uint64_t ReadVmid(uint64_t x) {
printf("Line %d\n", __LINE__);
Reg y;
static_assert(sizeof(x)==sizeof(y), "");
memcpy(&y, &x, sizeof(x));
return y.vmid;
}
 
#else
 
uint64_t ReadVmid(uint64_t x) {
printf("Line %d\n", __LINE__);
union {
uint64_t a;
Reg b;
} u;
u.a = x;
return u.b.vmid;
}
 

No comments: