Friday, December 9, 2016

Digest for comp.lang.c++@googlegroups.com - 24 updates in 4 topics

Marcel Mueller <news.5.maazl@spamgourmet.org>: Dec 09 09:32PM +0100

On 08.12.16 23.53, bitrex wrote:
 
> Am I correct in understanding that there's no way to treat this
> pool-allocated wrapper type as if it were a "regular" object
> instantiated on the stack?
 
Exactly. You cannot override the "operator.".
 
 
> obj.x = 7; //not okay, pool_object_t<MyPODStruct> has no member named "x"
 
> Maybe I should just make the pool_object_t more like a smart pointer,
 
Exactly too. You can virtualize only reference types.
In fact your type /is/ a reference type.
 
 
Marcel
bitrex <bitrex@de.lete.earthlink.net>: Dec 09 05:27PM -0500

On 12/09/2016 03:32 PM, Marcel Mueller wrote:
 
> Exactly too. You can virtualize only reference types.
> In fact your type /is/ a reference type.
 
> Marcel
 
Thanks. Reading a little more, I should probably make my pool class
conform to the "custom allocator" standard for C++11, and then I could
use it with STL containers. I could also write a smart pointer-like
wrapper around it to return lone reference objects.
bartekltg <bartek@gmail.com>: Dec 09 02:10AM +0100

On 07.12.2016 22:21, Richard wrote:
>> object with the time. You should only seed a generator once, so you
>> need to make the mt19937 object static:
 
> Nit: static objects like this make unit testing more difficult.
 
Do you prefer a global mt19937 object? ;>
 
bartekltg
bartekltg <bartek@gmail.com>: Dec 09 02:24AM +0100

On 07.12.2016 22:14, Ben Bacarisse wrote:
 
> need to make the mt19937 object static:
 
>> std::mt19937 gen(rd());
 
> static std::mt19937 gen(std::time(0));
 
You can meet in the middle,
std::random_device rd;
static std::mt19937 gen(rd() + std::time(0));
 
or something like:
 
auto t = std::chrono::high_resolution_clock::now();
std::chrono::time_point<std::chrono::high_resolution_clock> now() ;
static std::mt19937 gen2(rd() + t.time_since_epoch().count());
 
If random_device works, we have good seed, an addition would not break
it ( probably... No one can be sure that his random_device do not
terurn - std::time(0) ;-) and if it didn't work, seed still isn't
constant.
 
 
bartekltg
Christian Steins <cs01@quantentunnel.de>: Dec 09 11:24AM +0100

Am 09.12.2016 um 02:24 schrieb bartekltg:
 
> You can meet in the middle,
> std::random_device rd;
> static std::mt19937 gen(rd() + std::time(0));
 
Simple and good solution.
 
Until a get_seed() or something is added to the STL.
 
Christian
legalize+jeeves@mail.xmission.com (Richard): Dec 09 06:28PM

[Please do not mail me a copy of your followup]
 
bartekltg <bartek@gmail.com> spake the secret code
>>> need to make the mt19937 object static:
 
>> Nit: static objects like this make unit testing more difficult.
 
>Do you prefer a global mt19937 object? ;>
 
Perhaps, it depends on the situation.
 
A scoped static is essentially a global variable that you can't access
from outside that scope. This means that in a unit test scenario
you have no way in which you can reset this state. Therefore you
can't write a repeatable test of any code that is calling the
generator. The local statics are hidden global state.
 
Global state makes unit testing difficult.
 
The typical solution is to use dependency injection in order to allow
the code to be repeatably tested. In this case, injecting the
dependent state of the random number generator would solve the problem
and make the code testable. So yes, a global variable that is injected
by the caller would make this code more testable.
 
You can achieve the same end-user API by making a simple delegating
function that injects the global state and forwards any other
arguments. This frees callers from having to know about this global
state and the delegated function can still be unit tested.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
legalize+jeeves@mail.xmission.com (Richard): Dec 09 07:59PM

[Please do not mail me a copy of your followup]
 
(Richard) legalize+jeeves@mail.xmission.com spake the secret code
 
>Nit: static objects like this make unit testing more difficult.
 
Also nit: they can lead to difficult bugs in multi-threaded code.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
Ralf Goertz <me@myprovider.invalid>: Dec 09 09:37AM +0100

Hi,
 
consider the following program
 
#include <iostream>
 
struct X {
const int & cr;
int var;
X(const int &cr_) : cr(cr_),var(0) {}
X child() {
X ret(*this);
ret.var++;
return ret;
}
//X operator=(const X& other) {X ret(*this);return ret;} //(*)
};
 
int main() {
int k=42;
X x(k);
x=x.child();
std::cout<<x.var<<std::endl;
}
 
 
It doesn't compile without the operator definition (*). The error
message is
 
childtest.cc: In function 'int main()':
childtest.cc:18:6: error: use of deleted function 'X& X::operator=(X&&)'
x=x.child();
^
childtest.cc:3:8: note: 'X& X::operator=(X&&)' is implicitly deleted
because the default definition would be ill-formed:
 
struct X {
^
childtest.cc:3:8: error: non-static reference member 'const int&
X::cr', can't use default assignment operator
 
When I uncomment (*) it compiles but the program prints „0" instead of
the expected „1". There are a few ways to fix this. First, I could make
cr of type „int", so no reference and non-const. That would work. But in
the real world X is a heavy type and I need to x=x.child() all the time
in a recursive function. That would mean a waste of space and
performance. Also
 
X y=x.child()
 
and outputting y also works correctly without (*)
 
By the way, this was compiled using -std=c++11, but the problem is also
present without it. The only difference is it complaints about X&
instead of X&& in the deleted operator. What is going on and how can I
fix this?
 
Thanks
"Öö Tiib" <ootiib@hot.ee>: Dec 09 01:26AM -0800

On Friday, 9 December 2016 10:37:36 UTC+2, Ralf Goertz wrote:
> return ret;
> }
> //X operator=(const X& other) {X ret(*this);return ret;} //(*)
 
Note that here is rather unusual assignment operator commented
out that does not modify 'this' object at all (IOW does not assign).
May be it is the source of your self-confusion?
 
> std::cout<<x.var<<std::endl;
> }
 
> It doesn't compile without the operator definition (*).
 
How you want compiler to generate copy or move assignment?
Your class has reference member. References are immutable after
declaration so can not be neither copied nor moved to already
existing reference.
 
> The error message is
 
Basically saying exactly what what I said in lot better English and
more detail than I can produce.
 
> When I uncomment (*) it compiles but the program prints „0" instead of
> the expected „1".
 
The output "0" is what I would expect from the program
posted and with (*) uncommented. Can you tell why you expect
"1"?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 09 10:32AM +0100

On 09.12.2016 09:37, Ralf Goertz wrote:
> ^
> childtest.cc:3:8: error: non-static reference member 'const int&
> X::cr', can't use default assignment operator
 
And?
 
Isn't that clear?
 
 
Cheers!,
 
- Alf
Ralf Goertz <me@myprovider.invalid>: Dec 09 10:50AM +0100

Am Fri, 9 Dec 2016 10:32:33 +0100
> > X::cr', can't use default assignment operator
 
> And?
 
> Isn't that clear?
 
It is clear, that's why I tried to define my own assignment operator,
but I obviously failed. What would be the correct way to do it when I
really want cr to be a constant reference?
Ralf Goertz <me@myprovider.invalid>: Dec 09 10:52AM +0100

Am Fri, 9 Dec 2016 01:26:25 -0800 (PST)
 
> Note that here is rather unusual assignment operator commented
> out that does not modify 'this' object at all (IOW does not assign).
> May be it is the source of your self-confusion?
 
Yep that seems to be the problem. What would be the correct definition?
This definition
 
X operator=(const X& other) { cr=other.cr;var=other.var}
 
doesn't work either.
Paavo Helde <myfirstname@osa.pri.ee>: Dec 09 12:00PM +0200

On 9.12.2016 11:50, Ralf Goertz wrote:
 
> It is clear, that's why I tried to define my own assignment operator,
> but I obviously failed. What would be the correct way to do it when I
> really want cr to be a constant reference?
 
#include <iostream>
 
struct X {
const int & cr;
int var;
X(const int &cr_): cr(cr_), var(0) {}
X child() {
X ret(*this);
ret.var++;
return ret;
}
X& operator=(const X& other) {
this->~X();
new (this) X(other);
return *this;
}
};
 
int main() {
int k = 42;
X x(k);
x = x.child();
std::cout<<x.var<<std::endl;
}
Paavo Helde <myfirstname@osa.pri.ee>: Dec 09 12:06PM +0200

On 9.12.2016 12:00, Paavo Helde wrote:
> new (this) X(other);
> return *this;
> }
 
Correction:
 
X& operator=(const X& other) {
if (this!=&other) {
this->~X();
new (this) X(other);
}
return *this;
}
Ralf Goertz <me@myprovider.invalid>: Dec 09 11:09AM +0100

Am Fri, 09 Dec 2016 12:00:34 +0200
> new (this) X(other);
> return *this;
> }
 
Thanks, that seems to work. Do I need to worry about memory leakage
since I use new without delete?
"Öö Tiib" <ootiib@hot.ee>: Dec 09 02:50AM -0800

On Friday, 9 December 2016 12:09:35 UTC+2, Ralf Goertz wrote:
> > }
 
> Thanks, that seems to work. Do I need to worry about memory leakage
> since I use new without delete?
 
That code contains "placement new" not usual "new". It does not allocate
memory but instead uses memory that was given to it with argument.
Alain Ketterlin <alain@universite-de-strasbourg.fr.invalid>: Dec 09 01:58PM +0100

>> }
 
> Thanks, that seems to work. Do I need to worry about memory leakage
> since I use new without delete?
 
There is no memory allocation here, this can't cause leakage.
 
But you need to worry about your design: defining a struct with a const
ref member *and* an assignment operator does not make much sense.
Paavo's solution essentially bypasses the inherent incoherence by using
destructor and constructor, but the problem remains: your design is
absurd.
 
-- Alain.
Ralf Goertz <me@myprovider.invalid>: Dec 09 03:23PM +0100

Am Fri, 09 Dec 2016 13:58:38 +0100
> sense. Paavo's solution essentially bypasses the inherent incoherence
> by using destructor and constructor, but the problem remains: your
> design is absurd.
 
Okay, I am open to suggestions as to the design, although with Paavo's
solution, everything works as expected. My X is a class used in a
generic backtracking algorithm I have written. It contains the status
that changes when creating new chlidren or siblings.
 
template <class Status> class Backtrack {
bool findAll, isValid;
Status state;
bool reject();
bool accept();
Backtrack<Status> first();
Backtrack<Status> next();
void output();
public:
Backtrack(Status initial, bool fa=false) :
findAll(fa),state(initial),isValid(true) {}
void bt() {
//code according to the pseudo code in the wikipedia
//article on backtracking
}
};
 
I've used that code in a number of projects now by writing appropriate
functions reject(), accept(), first(), next(), and output(). It always
bothered me that I couldn't have members of Status which are const &,
although it might contain immutable information that is needed at all
levels of the search tree. My attempt is not to expose that information
if it is not necessary. Therefore, I want to avoid a global variable.
Also, a static member variable feels wrong since it must be accessed
from outside the class and I want to be able to have more than one
variable of class Backtrack<X> with different information in state. With
my design now I only need my „Special" Status class and
 
Backtrack<Special> b;
b.bt(Special(…),true);
 
and I can use different parameters in … As I said, „Special" can be very
big with only a few bits of information actually changing. Therefore, I
try to only make those parts variable and keep the rest const & as in
the example in the OP to avoid copying all the big stuff.
 
Any comments?
Paavo Helde <myfirstname@osa.pri.ee>: Dec 09 04:29PM +0200

On 9.12.2016 12:09, Ralf Goertz wrote:
>> }
 
> Thanks, that seems to work. Do I need to worry about memory leakage
> since I use new without delete?
 
No, there is no leak because there is no actual memory allocation involved.
 
However, you need to worry about self-assignment (fixed in my followup
post) and also you need to worry about exception throwing in the
constructor and destructor. If they happen to throw, then the object may
remain in an inconsistent/unusable state. In your simple example there
is no possibility of exceptions, but in real life this is something to
consider, and one might need to add some try-catch block and restore the
object into some valid fallback state.
 
In situations like that I have just used a pointer instead of the
reference, all this hassle is just not worth it.
 
Cheers
Paavo
Paavo Helde <myfirstname@osa.pri.ee>: Dec 09 05:08PM +0200

On 9.12.2016 16:23, Ralf Goertz wrote:
> big with only a few bits of information actually changing. Therefore, I
> try to only make those parts variable and keep the rest const & as in
> the example in the OP to avoid copying all the big stuff.
 
My solution basically works around this design and actually changes the
const references. If this is not what you wanted, then you should just
simply define an assignment operator which only changes the needed pieces:
 
#include <iostream>
 
struct X {
const int & cr;
int var;
X(const int &cr_): cr(cr_), var(0) {}
X child() {
X ret(*this);
ret.var++;
return ret;
}
X& operator=(const X& other) {
var = other.var;
return *this;
}
};
 
int main() {
int k = 42;
X x(k);
x = x.child();
std::cout<<x.var<<std::endl;
}
Ralf Goertz <me@myprovider.invalid>: Dec 09 04:37PM +0100

Am Fri, 09 Dec 2016 17:08:10 +0200
> var = other.var;
> return *this;
> }
 
Hm, how come that this->cr is still k? Just because the left side of =
must have existed before? But then this would be some weired assignment,
wouldn't it?
 
int k(42), j(4711);
X x(k), y(j);
x=y;
 
Now x.cr would still be k, right?
Paavo Helde <myfirstname@osa.pri.ee>: Dec 09 05:46PM +0200

On 9.12.2016 17:37, Ralf Goertz wrote:
>> }
 
> Hm, how come that this->cr is still k? Just because the left side of =
> must have existed before?
 
Assignment indeed means that the assigned object already exists before.
If it does not, then you have a constructor, not assignment.
 
> X x(k), y(j);
> x=y;
 
> Now x.cr would still be k, right?
 
Right.
 
The assignment is weird because references cannot be reseated. I thought
this is what you wanted ("keep the rest const [...] to avoid copying all
the big stuff").
 
The destructor+placement new trick works around this and actually
reseats the references. It is up to you to decide which behavior you need.
 
Cheers
Paavo
kushal bhattacharya <bhattacharya.kushal4@gmail.com>: Dec 08 09:08PM -0800

i have tried making the console input in different thread but there's some data miscrepencies going on in other words when i ruin different threads using console input one thread works fine but the other thread shows segmentation fault .Could u please tell me what is the real issue behind this ? why am i getting this type of behaviour ?
"Öö Tiib" <ootiib@hot.ee>: Dec 08 11:20PM -0800

On Friday, 9 December 2016 07:08:54 UTC+2, kushal bhattacharya wrote:
> using console input one thread works fine but the other thread
> shows segmentation fault .Could u please tell me what is the real
> issue behind this ? why am i getting this type of behaviour ?
 
The real reason for such misbehavior is that there are number of
programming defects in your code that are probably related to
synchronization of threads.
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: