Friday, December 23, 2016

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

Joseph Hesse <joeh@gmail.com>: Dec 22 06:22PM -0600

In the following example, if I define a set in main() everything
works but if I define it, in the same way, in a struct it doesn't work.
 
g++ -std=c++11 Set.cpp
 
Thank you, (especially your patience)
Joe
 
 
======================= Set.cpp ======================
#include <iostream>
#include <set>
 
class X
{
private:
int x;
public:
X(int a) : x(a) {}
friend bool Comp(const X &, const X &);
};
 
bool Comp(const X &xobj1, const X &xobj2)
{
return xobj1.x < xobj2.x;
}
 
struct Y
{
// error, Compiler says Comp is not a type, it is not a type
// it is a function ptr since it is the name of a function
std::set<X, bool (*)(const X &, const X &)> AnotherSetOfX(Comp);
};
 
int main()
{
// works fine
std::set<X, bool (*)(const X &, const X &)> SetOfX(Comp);
}
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 23 01:47AM +0100

On 23.12.2016 01:22, Joseph Hesse wrote:
> // works fine
> std::set<X, bool (*)(const X &, const X &)> SetOfX(Comp);
> }
 
There are three ways to initialize a data member of a class type object:
 
struct S{ int x{42}; };
struct T{ int x = 42; };
struct U{ int x; U():x{42}{} };
 
The last one defines a default constructor for `U`.
 
The two first specify a default initialization that can be overridden by
a constructor, and if it's not overridden it is as if it was done by the
constructor like the one in `U`.
 
• • •
 
I assume that you're doing this for learning & language exploration.
 
But for practical programming just do as Mr. Flibble wrote:
 
define an `operator<` for the class, e.g. like this:
 
struct Point
{
int x = 0;
int y = 0;
 
friend
auto operator<( Point const& a, Point const& b )
-> bool
{ return tie( a.x, a. y ) < tie( b.x, b.y ); }
};
 
… where `tie` is `std::tie` from the `<tuple>` header.
 
• • •
 
An alternative to `tie` and that kind of stuff, is to define a
three-valued `compare` function, like `std::string::compare`, and then
inherit from a class template that defines `<` and other relational
operators in terms of `compare`. The inherit-in-an-implementation is
called the Barton-Nackman trick. It's in Wikipedia and other places.
 
Cheers & hth.,
 
- Alf
Bo Persson <bop@gmb.dk>: Dec 23 07:27PM +0100

On 2016-12-23 01:22, Joseph Hesse wrote:
> // it is a function ptr since it is the name of a function
> std::set<X, bool (*)(const X &, const X &)> AnotherSetOfX(Comp);
> };
 
If Comp had been a type, AnotherSetOfX(Comp); would have declared a
function taking a Comp parameter and returning a set.
 
The syntax for member initializations was deliberatly designed so that
it could not be confused with declaring a function. So you can only use
= Comp or {Comp}, but not (Comp).
 
 
Bo Persson
scott@slp53.sl.home (Scott Lurndal): Dec 23 02:31PM


>The functions get_canvas_index() and get_source_index() are lacking the
>mutex lock. Any access to data which is concurrently modified needs a
>mutex lock.
 
Not necessarily - atomics are a viable alternative.
Paavo Helde <myfirstname@osa.pri.ee>: Dec 23 08:19PM +0200

On 23.12.2016 16:31, Scott Lurndal wrote:
>> mutex lock. Any access to data which is concurrently modified needs a
>> mutex lock.
 
> Not necessarily - atomics are a viable alternative.
 
Yes, atomics are fine in many situations, but not here, in the OP
example. They are updated and read concurrently by the
sync_canvas_and_input() function. If it was using 2 atomics instead,
then the values returned are not guaranteed to be in sync, which would
cause interesting bugs (swapped slices in the result).
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 23 01:55AM +0100

On 23.12.2016 01:33, Stefan Ram wrote:
 
> o size and alignment
> o set of valid values
> o set of permitted operations
 
In C++ one might consider the type `void`. It has no size or alignment,
no values, and no permitted operations. One can define an unlimited
number of similar types.
 
So I think he's attacking the problem of definition from the wrong end.
 
Instead of trying an all out definition of type one can say, hey, this
is the basic core concept of a data type. This other thingy is also
considered a type; it's similar in the following respects: [...]. And
then we have ..., which is..., and so on; this list is not complete.
 
 
> struct B { int x; };
 
> A and B now agree in everything on his slide, yet they are
> different types!
 
As I recall they would be considered identical in original K&R C.
 
Not entirely sure.
 
 
 
> have I now added a »new permitted operation« to the type
> »unsigned« and thereby changed it into a different (new)
> type?
 
Oh, Scott Meyers went on and on about that.
 
Worth googling up, I think.
 
 
> I might post a followup later with an attempt to give
> an answer to his question.
 
:)
 
 
Cheers!,
 
- Alf
Manfred <mx2927@gmail.com>: Dec 23 05:07AM +0100

On 12/23/2016 01:55 AM, Alf P. Steinbach wrote:
 
> In C++ one might consider the type `void`. It has no size or alignment,
> no values, and no permitted operations. One can define an unlimited
> number of similar types.
Even more, one might consider a forward declaration:
struct A;
 
It introduces a type A in a scope, yet incomplete, but that exists so
that it can be used to some extent:
A* p;
 
although it has no size (not even zero size) yet.
 
 
> So I think he's attacking the problem of definition from the wrong end.
I think this too.
 
> is the basic core concept of a data type. This other thingy is also
> considered a type; it's similar in the following respects: [...]. And
> then we have ..., which is..., and so on; this list is not complete.
 
I believe (at least in modern C and more in C++) a type is a fundamental
concept the language is built upon. As such, it is hardly defined in
terms of the categories of the language itself.
To me, a type is strictly coupled with the the concepts of
representation and semantics:
Representation is a broader concept than "contents", which would be the
second of the properties above.
Semantics is a broader concept than the third property above.
 
 
 
>> struct B { int x; };
 
>> A and B now agree in everything on his slide, yet they are
>> different types!
Even more:
typedef int A;
typedef int B;
 
Strictly speaking, to me these are two different types (otherwise I
would not define two of them).
 
Manfred <noname@invalid.add>: Dec 23 03:46PM +0100

On 12/23/2016 1:55 AM, Alf P. Steinbach wrote:
>> different types!
 
> As I recall they would be considered identical in original K&R C.
 
> Not entirely sure.
 
I am not sure about K&R C, but this post refers to the 1974 Dennis
Ritchie's C reference manual from Bell Labs that does exactly what you
are saying:
 
https://groups.google.com/d/msg/comp.lang.c/FzfjDCD3VY4/cJMNLRKlBwAJ
 
From supercat's post:
https://www.bell-labs.com/usr/dmr/www/cman.pdf
paying particular attention to 7.1.7 and 7.1.8
 
scott@slp53.sl.home (Scott Lurndal): Dec 23 05:45PM


>I am not sure about K&R C, but this post refers to the 1974 Dennis
>Ritchie's C reference manual from Bell Labs that does exactly what you
>are saying:
 
In the V6 C compiler, all MoS (Members of structure) were top-level
symbol table entries (thus they needed to be unique program-wide). This
is one reason that unix structs (e.g. struct stat) use prefixes on
the MoS names (e.g. st_size).
 
Since they were top-level symbol table items, one could use
the member names with any pointer, regardless of the pointer type
IIRC.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Dec 23 05:07PM

Hi,
 
Merry festivus. I hope everyone has an enjoyable winterval. Sausages.
 
/Flibble
Tim Rentsch <txr@alumni.caltech.edu>: Dec 22 09:43PM -0800


> [...] std::list::sort is *not* required to be stable. [...]
 
AFAICT C++03, C++11, and C++14 all require std::list::sort to
be a stable sort.
Tim Rentsch <txr@alumni.caltech.edu>: Dec 22 10:09PM -0800

> keep note of the last and middle elements of said lists. Then when
> partitioning them, you can choose their pivots from those three
> nodes. No need to scan the lists.
 
I think what you say is true, although it's a little tricky to
keep track of the middle element (in each of the two partitions)
because you don't know ahead of time how many elements will be in
each partition.
 
OTOH, there are lots of different things that can affect the
constants, and usually there are tradeoffs between different
choices. For example, dealing with linked lists makes it easy to
divide the initial list into, say, 16 different sublists based on
15 different pivot values, and recurse on each sublist before
gluing them together. For this scheme we might use random
sampling to get the 15 pivot values (for each sublist, ready for
the next pass), which greatly reduces the chance of O(n**2)
behavior, and may give an improvement in the constant factor as
well. (A value may be assigned to a sublist using just 4 or 5
compares, depending on whether a compare operation gives 1 bit
of information or a {less, equal, greater} result.) And of
course there are local optimizations to consider, which often
are good for a factor of, oh, let's say 1.5 or 2; but then
again these may be swamped by the cost of doing the compares.
 
I guess my general rule is that anything affecting just the
constants is a possible optimization that I leave for such time
as performance has been shown to be an issue. Before then I
pretend not to care what the constants are. :)
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Dec 23 05:00PM

On 23/12/2016 06:09, Tim Rentsch wrote:
 
[snip]
 
> keep track of the middle element (in each of the two partitions)
> because you don't know ahead of time how many elements will be in
> each partition.
 
^^ this. My initial guess that worst case performance is more likely is
starting to get legs I think. :D Sausages.
 
/Flibble
Tim Rentsch <txr@alumni.caltech.edu>: Dec 22 10:48PM -0800

> 10: endwhile
> 11: SortSNi(indescendingorderofCostij)
> 12: NHi=FirstelementofthelistSNi
 
I'm trying to resist the temptation to post C++ code for this
pseudocode... oh what the heck....
 
typedef std::vector<int> VI;
 
void
something( VI Ni, int Hopmin, int i, VI SNi, int *NHi ){
auto Costij = 0;
extern void Compute( int );
auto j2Ni = 0;
for( auto node : Ni ){
Compute( Costij ),j2Ni;
}
auto j = Ni.begin();
while( ! (j == Ni.end()) ){
if( Hopmin, *j+1 == Hopmin, i ){
SNi.push_back( *j );
}
j += 1;
}
extern void SortSNI( int );
SortSNI( Costij );
*NHi = SNi.front();
}
 
The Compute() and SortSNI() functions need to be supplied, and
there may be a few other details in need of correction. I'm sure
though that these are minor issues now that the pseudocode has
been faithfully translated.
 
 
P.S. I hope y'all will forgive my little joke. Merry Christmas!
woodbrian77@gmail.com: Dec 23 08:14AM -0800

On Friday, December 23, 2016 at 12:48:59 AM UTC-6, Tim Rentsch wrote:
> though that these are minor issues now that the pseudocode has
> been faithfully translated.
 
> P.S. I hope y'all will forgive my little joke. Merry Christmas!
 
Happy Chanukah also.
 
 
Brian
Ebenezer Enterprises - "If someone curses their father or mother,
their lamp will be snuffed out in pitch darkness." Proverbs 20:20
 
http://webEbenezer.net
ram@zedat.fu-berlin.de (Stefan Ram): Dec 23 12:33AM

Dan Sacks asked (in the context of C and C++), »What's a data
type?«.
 
(Maybe you want to pause here and think about it yourself
for a moment.)
 
He later gave his answer. From his slide:
 
A data type is a bundle of compile-time properties
for an object:
 
o size and alignment
o set of valid values
o set of permitted operations
 
Well, if he would have asked me this question, I would have
started to stutter and said some drivel. Later, when I would
have time to think about it, I might think the best answer
would be to ask him whether he refers to a specific
programming language, and, if so, to which programming
language, and then whether I may now take some time (an
hour?) to thing about my answer.
 
But I am not sure whether I would deem his slide to be a
satisfying answer! One reason would be this:
 
struct A { int x; };
struct B { int x; };
 
A and B now agree in everything on his slide, yet they are
different types!
 
An abstract data types can hide its »values« up to the
point where they are not a known determined set anymore.
 
And when I define a function, say
 
unsigned successor( unsigned const i ){ return i + 1u; }
 
have I now added a »new permitted operation« to the type
»unsigned« and thereby changed it into a different (new)
type?
 
I might post a followup later with an attempt to give
an answer to his question.
ram@zedat.fu-berlin.de (Stefan Ram): Dec 23 12:39AM

>// error, Compiler says Comp is not a type, it is not a type
>// it is a function ptr since it is the name of a function
>std::set<X, bool (*)(const X &, const X &)> AnotherSetOfX(Comp);
 
You are using an initializer in the member declaration
in the class specifier. Such an initializer needs to be
a braced initializer or an equals initializer. And it is
only possible with a recent C++ at all. So, you might try,
 
std::set<X, bool (*)(const X &, const X &)> AnotherSetOfX{Comp};
 
.
ram@zedat.fu-berlin.de (Stefan Ram): Dec 23 12:54AM

>On 23.12.2016 01:22, Joseph Hesse wrote:
>>X(int a) : x(a) {}
 
The above constructor might also be written
with »explicit« to forbid implicit conversions.
 
>struct S{ int x{42}; };
>The two first specify a default initialization that can be overridden by
>a constructor
 
And, it seems (I only tried it with an implementation),
also with am aggregate initializer by the client.
(The execution shows that the in-class initializer of
the class »pair« is not used.)
 
#include <iostream>
#include <ostream>
#include <string>
 
using namespace ::std::literals;
 
template< class C >
C value( C const x )
{ ::std::cout << "value: "s << x << '\n';
return x; }
 
struct pair
{ double b{ value( 1.0 ) }; };
 
int main()
{ pair o{ value( 2.0 ) };
::std::cout << o.b << '\n'; }
 
transcript
 
value: 2
2
ram@zedat.fu-berlin.de (Stefan Ram): Dec 23 03:30PM

>Basically the problem is to map a (HWND, WM_PAINT) pair to a
>window->on_wm_paint() handler.
...
>I agree on all of your critics to MFC/ATL, but I haven't find a good
>dispatch method either.
 
What is bothering you most about the dispatch methods that
you have been using so far?
legalize+jeeves@mail.xmission.com (Richard): Dec 22 11:59PM

[Please do not mail me a copy of your followup]
 
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
 
>> ATL is now available with Community Edition, so there is no longer a
>> dollar cost to selecting ATL for use in your program.
 
>I think maybe you mean WTL, which was derived from ATL.
 
WTL was always free, but it built on ATL which wasn't free until the
recent versions of VS Community Edition.
--
"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>
Tim Rentsch <txr@alumni.caltech.edu>: Dec 22 11:02PM -0800

> // via the message cracker macros in <windowsx.h>. [...]
 
> I've done this so many times in the past, with C++03. But I feel
> that there must be some less unclean modern C++-ish way. Ideas?
 
I share your reaction, but what is it you hope to accomplish? The
definition for WINAPI_DISPATCH can be simplified fairly easily I
think (and get rid of the others), which also could make it possible
to write
 
switch( m.message_id ){
WINAPI_DISPATCH( m, WM_COMMAND, Main_window, on_wm_command );
WINAPI_DISPATCH( m, WM_PAINT, Main_window, on_wm_paint );
WINAPI_DISPATCH( m, WM_SIZE, Main_window, on_wm_size );
}
 
so the surrounding #define/#undef would not be needed. But what is
it you are looking for?
Manfred <noname@invalid.add>: Dec 23 03:35PM +0100

On 12/22/2016 11:22 PM, Alf P. Steinbach wrote:
> ATL/WFC suffers from being designed by incompetents, including the goal
> of running ActiveX controls in a browser (imagine that idea! shudder!),
> even though there's some modern C++ stuff like templating.
 
I agree on all of your critics to MFC/ATL, but I haven't find a good
dispatch method either.
Basically the problem is to map a (HWND, WM_PAINT) pair to a
window->on_wm_paint() handler.
I am no fan of switch or maps for this, and it looks to me too that
there should be a better way to accomplish this - in the end, it is what
a virtual method call would be for.
 
If I remember correctly, from a long time ago, Borland's Turbo C++ used
the extra window bytes to store the window object pointer, and used some
tweaking of the vtable in place of the switch statement (at least this
is what it looked like from the sintax I remember). Both of which were
rather non-portable, but in my memory would be in the direction to a
better dispatching - obviously if it were done with the facilities
offered by nowadays's standard.
 
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 23 03:50PM +0100

On 23.12.2016 08:02, Tim Rentsch wrote:
 
>> I've done this so many times in the past, with C++03. But I feel
>> that there must be some less unclean modern C++-ish way. Ideas?
 
> I share your reaction, but what is it you hope to accomplish?
 
Something ... less macro-ish, I guess. :)
 
Or if you mean what these macros do (i.e. message cracking is not a
familiar term to you, it is after all very Windows API-level specific),
they take 64 bits of information in a specific packed message, unpacks
that into 0 to about 4 argument values depending on the message, and
calls a specified handler function with those unpacked arguments.
 
The problem is the knowledge of how to pack/unpack specific messages: it
is of course documented, but the only API level support for packing, the
only /code/ for that that can be leveraged, is as far as I know provided
by the macros from <windowsx.h>.
 
 
> WINAPI_DISPATCH( m, WM_SIZE, Main_window, on_wm_size );
> }
 
> so the surrounding #define/#undef would not be needed.
 
Oh, thanks. :) But I added the #define/#undef mechanism to avoid having
to repeat the class name. Mostly for convenience and the DRY principle,
Don't Repeat Yourself, but also because conceivably the class name could
in some instance be a template expression with commas in it.
 
(There is a simple workaround for comma in a macro argument, namely
always enclose that argument in parentheses, and unpack it in the macro,
but that adds some dirtyness again. Another workaround is to define a
macro symbol as comma, but that's really dirty.)
 
 
> But what is it you are looking for?
 
I don't know.
 
Some really out-of-the-box idea, I guess.
 
Or maybe there is a library somewhere that (just) provides unpacking of
most all defined window messages, like that.
 
Hm, now you me thinking.
 
 
Cheers!,
 
- Alf
busybizz bizz <bisy2648@gmail.com>: Dec 23 03:31AM -0800

Painting Contractors in Bangalore - List of top painting services, works, companies in Bangalore and get painting price, companies contact addresses, phone numbers, ratings and evaluations right away on busybizz.com
http://busybizz.com/Painting-Contractors-Bangalore.php
Tim Rentsch <txr@alumni.caltech.edu>: Dec 22 10:24PM -0800


> How many classes do you think is required to handle the input? Any
> other thoughts or suggestions on the class design would really be
> appreciated?.
 
Assuming I understand you correctly, what you want is something
like an array, or "parallel arrays", indexed by something numeric
or close to numeric (integers?), out of which you can extract
three (or up to three) independent values for each index. Is
this a fair statement of your problem?
 
If it is, I would start with something like this (disclaimer: not
tested!):
 
#include <vector>
 
struct xyz_table {
struct xyz { double x, y, z; };
std::vector <xyz> stuff;
 
void add( double x ){ add( x, 0, 0 ); }
void add( double x, double y ){ add( x, y, 0 ); }
void add( double x, double y, double z ){ stuff.push_back( {x,y,z} ); }
 
xyz& operator[]( size_t n ){ return stuff[n]; }
};
 
void
use_xyz_table_example(){
xyz_table foo;
 
foo.add( 1, 2, 3 );
foo.add( 2, 3, 4 );
foo.add( 3, 4, 5 );
foo.add( 4, 5, 6 );
foo.add( 5, 6, 7 );
foo.add( 6, 7, 8 );
 
foo[3].x = 7;
foo[5].z = foo[2].y;
}
 
and not worry about any extra space taken up by "unused" values,
nor about flagging access to unavailable "coordinates".
 
Of course, if those things matter, it isn't hard to have two
more classes (disclaimer: not compiled):
 
 
struct xy_table {
struct xy { double x, y; };
std::vector <xy> stuff;
 
void add( double x, double y ){ stuff.push_back( {x,y} ); }
 
xy& operator[]( size_t n ){ return stuff[n]; }
};
 
 
struct x_table {
struct x { double x, y; };
std::vector <x> stuff;
 
void add( double x ){ stuff.push_back( {x} ); }
 
x& operator[]( size_t n ){ return stuff[n]; }
};
 
 
and use x_table, xy_table, or xyz_table, as appropriate.
 
If the data type being stored is some type other than double,
that can be made (one or more) template parameters. (And
hopefully you know enough to find out how to do that so I don't
need to explain it...)
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: