Thursday, March 30, 2017

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

Vir Campestris <vir.campestris@invalid.invalid>: Mar 30 09:59PM +0100

On 20/03/2017 07:40, Juha Nieminen wrote:
 
> If you think you can, then prove it. Give me a function that will take
> a linked list and a value, and will insert the value in the middle of
> the list inexpensively.
 
The insertion is cheap. It's finding the place that's expensive.
 
Andy
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Mar 30 02:09PM -0700

On Thursday, March 30, 2017 at 4:59:20 PM UTC-4, Vir Campestris wrote:
> > a linked list and a value, and will insert the value in the middle of
> > the list inexpensively.
 
> The insertion is cheap. It's finding the place that's expensive.
 
Potentially. Link lists are not ideal in every situation, but if you
are tracking through data and have anchors where you know where things
need to be inserted, then it is very nice.
 
It also makes parsing things easy. By creating a component link list,
and then processing through the components, you can translating, re-
arrange, delete, inject, as needed.
 
Thank you,
Rick C. Hodgin
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 30 02:58AM +0200

On 29-Mar-17 11:00 PM, Mr Flibble wrote:
> Linux uses UTF-8 for filenames
 
If so then Linux has diverged in an incompatible way from Unix mainstream.
 
Of old a Unix filename was just a sequence of bytes with no interpretation.
 
In particular, uppercasing or lowercasing a name was meaningless.
 
 
Cheers!,
 
- Alf
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 30 03:02AM +0200

On 30-Mar-17 2:58 AM, Alf P. Steinbach wrote:
 
> If so then Linux has diverged in an incompatible way from Unix mainstream.
 
> Of old a Unix filename was just a sequence of bytes with no interpretation.
 
> In particular, uppercasing or lowercasing a name was meaningless.
 
And, sorry, I was half asleep, a Unix filename could be invalid as UTF-8.
 
 
Cheers!,
 
- Alf
Daniel <danielaparker@gmail.com>: Mar 29 07:24PM -0700

On Wednesday, March 29, 2017 at 8:58:29 PM UTC-4, Alf P. Steinbach wrote:
> > Linux uses UTF-8 for filenames
 
> If so then Linux has diverged in an incompatible way from Unix mainstream.
 
> Of old a Unix filename was just a sequence of bytes with no interpretation.
 
Any sequence of bytes except for the forward slash / or the NUL byte. That
applies to Linux too. UTF-8 encoded filenames are fine, but so are filenames
in any other encoding. As a practical matter, though, some applications
may have difficulty with some encodings. I think it's fair to say that it's
considered best practice in Linux to use UTF-8 encoded filenames.
 
Daniel
Daniel <danielaparker@gmail.com>: Mar 29 08:46PM -0700

On Wednesday, March 29, 2017 at 5:00:48 PM UTC-4, Mr Flibble wrote:
> represented by a single scalar type are just as useless as variable
> length UTF-8 encoded codepoints as far as wanting an atomic "character"
> is concerned
 
I don't understand your point. Given a std::string that contains UTF-8
encoded bytes, some operations can be performed on that std::string without
iterating over the codepoints (or equivalently the UTF-8 character
sequences), for instance, compare equal with another UTF-8 encoded string.
But others cannot, for example, none of the std::string find operations will
work. I suppose you could specialize char_traits in basic_string with a
unicode version, but that leads to other issues.
 
 
> I strongly disagree with your assertion that UTF-8 should only be used
> during "serialization"
 
I never asserted that. My own view is that UTF-8 is probably the preferred
string _buffer_ encoding. wstring has been 32 bit on UNIX for a very long
time, and never gained any significant adoption in applications that have had
to support Unicode. I can't see u32string doing any better.
 
> and that an application should be unaware of it
 
I do believe that :-)
 
Most modern languages have one string class with a standard string interface,
not string, wstring, u16string, u32string, whole bunch of basic_string
possibilities with different character types, char_traits, allocators.
Instead of embuing encoding information in the type, they have an internal
type, and functions getBytes(encoding), toBytes(encoding) to convert the
internal representation from/to one of many possible external encoded types.
There's enough prior experience now to suggest that that's the right
approach.
 
Daniel
Robert Wessel <robertwessel2@yahoo.com>: Mar 30 01:13AM -0500


>http://stackoverflow.com/a/6972551/597607
 
>the 2200 series even had a C++ compiler. Or at least an eye-witness
>claims to have once seen the manual on-line. :-)
 
 
http://public.support.unisys.com/2200/docs/cp14.0/pdf/78310422-011.pdf
https://public.support.unisys.com/2200/docs/cp15.0/pdf/78310430-016.pdf
David Brown <david.brown@hesbynett.no>: Mar 30 10:00AM +0200

On 30/03/17 02:58, Alf P. Steinbach wrote:
> On 29-Mar-17 11:00 PM, Mr Flibble wrote:
>> Linux uses UTF-8 for filenames
 
> If so then Linux has diverged in an incompatible way from Unix mainstream.
 
It has not - Mr. Flibble is wrong. Like all *nix systems, Linux
filenames are a sequence of 8-bit characters terminated in \0. The only
characters disallowed in the names are / (reserved for directories) and
\0 (the terminator).
 
It is up to the shell, file manager, desktop, etc., to interpret the
filenames in any it wants. In the early days, ASCII was the common
interpretation. Then people started using 8-bit code pages for
different locales, before UTF-8 became dominant.
 
In modern systems, UTF-8 is by far the most common encoding (with the
huge majority of file names matching the ASCII encoding), but it is not
required by the native filesystems or the OS.
 
Some non-native filesystems, such as NTFS and VFAT, /do/ have
requirements on character encoding (such as UCS-2 / UTF-16 / whatever
half-made jumble MS picked for that particular version of the
filesystem), and Linux will of course follow the rules there.
 
David Brown <david.brown@hesbynett.no>: Mar 30 10:05AM +0200

On 30/03/17 05:46, Daniel wrote:
> But others cannot, for example, none of the std::string find operations will
> work. I suppose you could specialize char_traits in basic_string with a
> unicode version, but that leads to other issues.
 
Why won't "find" work with UTF-8 strings? UTF-8 is self-synchronising -
if you search for one UTF-8 string inside another, matches done as
Unicode code points will be the same as matches done as raw 8-bit data.
David Brown <david.brown@hesbynett.no>: Mar 30 10:06AM +0200

On 29/03/17 17:08, Scott Lurndal wrote:
>> can, of course, provide smaller divisions - but they are not "bytes" in
>> C parlance.
 
> Yes, the 48-bit systems have six 8-bit bytes.
 
Sorry - I misread your post as saying that 48-bit words were decomposed
into "6-bit bytes", not "6 bytes".
Bo Persson <bop@gmb.dk>: Mar 30 10:57AM +0200

On 2017-03-30 08:13, Robert Wessel wrote:
>> claims to have once seen the manual on-line. :-)
 
> http://public.support.unisys.com/2200/docs/cp14.0/pdf/78310422-011.pdf
> https://public.support.unisys.com/2200/docs/cp15.0/pdf/78310430-016.pdf
 
Oh, thanks! :-)
 
 
 
Bo Persson
Daniel <danielaparker@gmail.com>: Mar 30 05:30AM -0700

On Thursday, March 30, 2017 at 4:05:22 AM UTC-4, David Brown wrote:
 
> Why won't "find" work with UTF-8 strings? UTF-8 is self-synchronising -
> if you search for one UTF-8 string inside another, matches done as
> Unicode code points will be the same as matches done as raw 8-bit data.dd
 
Good point. I hadn't thought of that, thanks.
 
Daniel
David Brown <david.brown@hesbynett.no>: Mar 30 04:10PM +0200

On 30/03/17 14:30, Daniel wrote:
>> if you search for one UTF-8 string inside another, matches done as
>> Unicode code points will be the same as matches done as raw 8-bit data.dd
 
> Good point. I hadn't thought of that, thanks.
 
And I thought it was I who had missed something here.
 
The self-synchronising aspect of UTF-8 was a key design point, and I
think the ability to find substrings was a major reason for having it.
Vir Campestris <vir.campestris@invalid.invalid>: Mar 30 09:49PM +0100

On 29/03/2017 13:54, Scott Lurndal wrote:
> four would be packed into a 36-bit word). On 48-bit systems[**], a word
> can be decomposed into 6 bytes using various instructions, but individual
> byte access to memory isn't supported.
 
_Was_ is the operative word. I first learned assembly on a DECSystem10.
The 36 bit words normally contained 5 7-bit characters, with a spare
bit. There was no byte access. I've also used ICL1900s (24 bit word, 4x6
bit characters) and a weird TI graphics processor where you could have a
packed array of items of any (small) number of bits. Handy when you want
to address a display with 8 greys per pixel. And yes, we did program
that one in C!
 
But this was all a long time ago...
 
Andy
Jeff-Relf.Me @.: Mar 30 01:07PM -0700

Manfred <invalid@invalid.add>: Mar 30 12:24AM +0200


> I'm wondering if there are things with my Windows makefile
> that could be improved on:
 
> https://bitbucket.org/webenezer/onwards/src/7a925499bdaa2ce53df5401f255b2db9d6100bf0/makefile.windows?at=master&fileviewer=file-view-default
 
quicklz.obj: quicklz.h
$(CC) $(CFLAGS) -c quicklz.c
 
marshalling_integer.obj: marshalling_integer.hh
$(CC) $(CFLAGS) -c marshalling_integer.cc
 
The above should indicate the .c and .cc sources as dependencies
Jorgen Grahn <grahn+nntp@snipabacken.se>: Mar 30 07:08PM

On Wed, 2017-03-29, Richard wrote:
 
>>Perhaps, but the cost of copying the source code to whereever you want
>>to build, and building it there, is very small today.
 
> That sounds to me like you haven't tried to do what you suggest
 
What do I suggest?
 
> with any sizeable distribution or with any project that has a mildly
> complex build.
 
For the size, Make scales really well. One more source file, one more
line in the Makefile. (If you write decent Makefiles, which I do.)
 
For complexity, almost no systems have a complex build these days --
except when the build system itself is the source of complexity.
 
> In those situations where I've attempted to do what you suggest, it
> was significantly more painful than just running CMake. CMake
> supports this trivially out-of-the-box using the same source tree.
 
I don't quite understand. For someone else's project, you build with
whatever they offer. If that project uses CMake, you build using
CMake. (For me, it's usually a .configure script.)
 
If it was my project, I'd probably choose a plain Makefile.
 
Granted, there /are/ exceptions. Like the Linux kernel, where extreme
configurability is a must. Plain Make would not work there -- there's
no fixed dependency graph. But I'm not Linus, and I don't run any
projects like that. I won't place that kind of cost on a project
which doesn't need it, just because some /other/ project does.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Lynn McGuire <lynnmcguire5@gmail.com>: Mar 30 12:20PM -0500

On 3/26/2017 3:30 PM, Stefan Ram wrote:
> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
...
> called »C++19/20« by some now).
 
> Of course with regard to a graphical output or a GUI, there does
> not even seem to be a TS in sight.
 
What is a TS ?
 
Thanks,
Lynn
scott@slp53.sl.home (Scott Lurndal): Mar 30 05:29PM


>> Of course with regard to a graphical output or a GUI, there does
>> not even seem to be a TS in sight.
 
>What is a TS ?
 
First hit on google "C++ TS" gives the answer.
bitrex <bitrex@de.lete.earthlink.net>: Mar 30 09:49AM -0400

Suppose I have a structure like this, where a wrapper class for a POD
struct has a static memory buffer, and on construction a copy of the POD
struct is placed in it via placement new. Then another class wraps that,
and using the CRTP ensures that each child class has its own copy of the
buffer (rather than one being shared among all the subclasses.)
 
And suppose I have a "constexpr" function that creates a constant vector
or array of these objects at runtime, initialized with the default
constructor. The classes inside just sit around holding their static
buffer and a nullptr.
 
And then I create a stack data structure holding pointers to those
objects. What I'd like to be able to do is pop a pointer off the stack,
dereference it, and assign it such that the operation constructs a new
wrapper holding my POD data "in place" in the vector/array of originally
default-initialized objects.
 
I was thinking "PODWrapper" could also hold a reference to the stack, so
that the destructor would push its own "this" pointer back on it when
the wrapper went out of scope.
 
I'm not sure the best way to write the copy constructors for the
following two classes such that dereferencing and assignment for this
type of class is possible, though, without ending up with memcpys that
try to use the same source and destination argument.
 
#include <cstring>
 
struct POD
{
int a;
int b;
int c;
};
 
template <template <typename> class Derived,
typename T>
struct PODHolder
{
virtual ~PODHolder() {}
 
operator T() const { return *pod_ptr_; }
T* operator&() const { return pod_ptr_; }
T* operator&(const PODHolder& other) const { return pod_ptr_; }
 
protected:
PODHolder() = default;
 
PODHolder(const T& pod) :
pod_ptr_(new (_pod_buf()) T(pod))
{}
 
PODHolder(const T* pod) : pod_ptr_(_pod_buf())
{
std::memcpy(pod_ptr_, pod, sizeof(T));
}
 
private:
static char* _pod_buf()
{
static auto buf = new char[sizeof(T)];
return &buf[0];
}
 
T *const pod_ptr_ = nullptr;
};
 
template <typename T>
struct PODWrapper : public PODHolder<PODWrapper, T>
{
PODWrapper() = default;
 
PODWrapper(const T& pod) :
PODHolder<PODWrapper,T>(pod) {}
 
PODWrapper(const T* pod) :
PODHolder<PODWrapper,T>(pod) {}
};
bitrex <bitrex@de.lete.earthlink.net>: Mar 30 09:53AM -0400

On 03/30/2017 09:49 AM, bitrex wrote:
 
> {
> static auto buf = new char[sizeof(T)];
> return &buf[0];
 
sorry, should be just "return buf;" here as buf is already a pointer.
ram@zedat.fu-berlin.de (Stefan Ram): Mar 30 12:05PM

I was reading an article by N. Wirth about "Program
Development by Stepwise Refinement" from 1971.
 
It is discussing the Eight Queens Problem and says:
 
»The reader is strongly urged to try to find a
solution by himself before embarking on the paper«.
 
Argh! So, now, I couldn't read on, but had to solve
the silly Eight Queens Problem myself first!
 
I read it mentioned so very often, but never actually
programmed a solution myself IIRC. So here it is in C++:
 
#include <algorithm>
#include <cassert>
#include <iostream>
#include <ostream>
#include <vector>
#include <string>
 
using position_t = int;
using direction_t = int;
 
::std::vector< direction_t >directions{ 0, 1, 2, 3, 4, 5, 6, 7 };
::std::vector< int >offset_y{ +1, +1, 0, -1, -1, -1, 0, +1 };
::std::vector< int >offset_x{ 0, +1, +1, +1, 0, -1, -1, -1 };
 
class board_t : public ::std::vector< position_t >
{ public:
 
using ::std::vector< position_t >::vector;
 
board_t(): board_t( 64 ){}
 
int operator()( int const y, int const x ) const
{ return this->at( y * 8 + x ); }
 
void set( position_t const position )
{ assert( !this->at( position ));
this->at( position )= 1; }
 
void unset( position_t const position )
{ assert( this->at( position ));
this->at( position )= 0; }
 
bool is_in_board( int const position ) const
{ return position >= 0 && position < 64; }
 
bool is_in_board( int const y, int const x ) const
{ return y >= 0 && y < 8 && x >= 0 && x < 8; }
 
bool conflict_with_other_position
( int const position_y, int const position_x ) const
{ for( direction_t const direction : directions )
{ int const dy = offset_y.at( direction );
int const dx = offset_x.at( direction );
int pos_y = position_y;
int pos_x = position_x;
for( int distance = 0;; ++distance )
{ pos_y += dy;
pos_x += dx;
if( !is_in_board( pos_y, pos_x ))break;
if( ( *this )( pos_y, pos_x ))return true; }}
return false; }
 
bool conflict_with_other_position( position_t const position ) const
{ return conflict_with_other_position( position / 8, position % 8 ); }
 
bool conflict_with_this_position( position_t const position ) const
{ return this->at( position ); }
 
bool conflict( position_t const position ) const
{ assert( is_in_board( position ));
if( conflict_with_this_position( position ))return true;
return conflict_with_other_position( position ); }
 
void print_cell_at( int const row, int const col ) const
{ ::std::cout <<( ( *this )( row, col )? 'W' : ':' ); }
 
void print_end_of_line() const
{ ::std::cout << '\n'; }
 
void print_all_cells_of( int const row ) const
{ for( int col = 0; col < 8; ++col )print_cell_at( row, col );
print_end_of_line(); }
 
void print_all_rows() const
{ for( int row = 8; row > 0; ){ --row; print_all_cells_of( row ); }}
 
void print() const
{ print_all_rows(); }};
 
static void print( board_t const & board )
{ board.print();
::std::cout << '\n'; }
 
struct place_eight_queens
{
int number_of_queen {};
 
board_t board;
 
void print_solution_or_set_next_queen( position_t const position )
{ if( 8 == number_of_queen )print( board );
else place_next_queen( position ); }
 
void set_this_queen( position_t const position )
{ board.set( position );
print_solution_or_set_next_queen( position );
board.unset( position ); }
 
void set_queen_if_no_conflict( position_t const position )
{ if( !board.conflict( position ))set_this_queen( position ); }
 
void try_all_positions( int const starting_position )
{ for( position_t position = starting_position; position < board.size(); ++position )
set_queen_if_no_conflict( position ); }
 
void place_next_queen( int const starting_position )
{ ++number_of_queen;
try_all_positions( starting_position );
number_of_queen--; }
 
void place_queens()
{ number_of_queen = 0;
int const starting_position = 0;
place_next_queen( starting_position ); }
 
void run() { place_queens(); }};
 
int main() { ::place_eight_queens{}.run(); }
 
I have not yet compared the output with solutions from the
literature, so I don't know whether it's correct.
 
Problem: The function »conflict_with_other_position(int,int)«
is way too long, but I was not yet able to find a elegant
decomposition into several smaller function with less than
three parameters each.
ram@zedat.fu-berlin.de (Stefan Ram): Mar 30 12:16PM

>::std::vector< direction_t >directions{ 0, 1, 2, 3, 4, 5, 6, 7 };
>::std::vector< int >offset_y{ +1, +1, 0, -1, -1, -1, 0, +1 };
>::std::vector< int >offset_x{ 0, +1, +1, +1, 0, -1, -1, -1 };
 
I possibly should have used »::std::array« above, following
the guideline to prefer »::std::array« to »::std::vector«
when »::std::vectors« advanced features (resizing) are not
needed.
 
Also, I am told:
 
warning: declaration requires a global destructor [clang-diagnostic-global-constructors]
::std::vector< direction_t >directions{ 0, 1, 2, 3, 4, 5, 6, 7 };
^
. Don't know what to make of this.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 30 01:40PM +0200

In C++03 perfect forwarding of a sequence of arguments of arbitrary
types, caused a combinatorial explosion in const versus non-const.
 
In C++11 and later even just writing a function that /accepts/ arbitrary
argument types, when it's desirable to accept std::initializer_list
literals such as `{1, 2, 3}`, causes a combinatorial explosion in
initializer_list (which must known to the compiler as such) versus others.
 
E.g. in order to be able to call
 
multi( {1, 2, 3}, {5, 6, 7} )
 
with up to 3 arguments, a bunch of silly overloads are apparently needed:
 
template< class... Collections >
class Multidimensional_view_
{
public:
Multidimensional_view_( Collections const&... )
{}
};
 
template< class... Collections >
inline $f make_multidimensional_view( ref_<const Collections>... c )
-> Multidimensional_view_< Collections... >
{ return Multidimensional_view_< Collections... >{ c... }; }
 
template< class... Collections >
inline auto multi( ref_<Collections>... c )
{ return make_multidimensional_view( c... ); }
 
template< class Value >
// i
inline auto multi(
ref_<const initializer_list<Value>> list
)
{ return make_multidimensional_view( list ); }
 
template< class Collection, class Value >
// ci
inline auto multi(
ref_<const Collection> c,
ref_<const initializer_list<Value>> list
)
{ return make_multidimensional_view( c, list ); }
 
template< class Value, class Collection >
// ic
inline auto multi(
ref_<const initializer_list<Value>> list,
ref_<const Collection> c
)
{ return make_multidimensional_view( list, c ); }
 
template< class Value_1, class Value_2 >
// ii
inline $f multi(
ref_<const initializer_list<Value_1>> list_1,
ref_<const initializer_list<Value_2>> list_2
)
{ return make_multidimensional_view( list_1, list_2 ); }
 
template< class Collection_1, class Collection_2, class Value >
// cci
inline auto multi(
ref_<const Collection_1> c_1,
ref_<const Collection_2> c_2,
ref_<const initializer_list<Value>> list
)
{ return make_multidimensional_view( c_1, c_2, list ); }
 
template< class Collection_1, class Value, class Collection_2 >
// cic
inline auto multi(
ref_<const Collection_1> c_1,
ref_<const initializer_list<Value>> list,
ref_<const Collection_2> c_2
)
{ return make_multidimensional_view( c_1, list, c_2 ); }
 
template< class Collection, class Value_1, class Value_2 >
// cii
inline auto multi(
ref_<const Collection> c,
ref_<const initializer_list<Value_1>> list_1,
ref_<const initializer_list<Value_2>> list_2
)
{ return make_multidimensional_view( c, list_1, list_2 ); }
 
template< class Value, class Collection_1, class Collection_2 >
// icc
inline auto multi(
ref_<const initializer_list<Value>> list,
ref_<const Collection_1> c_1,
ref_<const Collection_2> c_2
)
{ return make_multidimensional_view( list, c_1, c_2 ); }
 
template< class Value_1, class Collection, class Value_2 >
// ici
inline auto multi(
ref_<const initializer_list<Value_1>> list_1,
ref_<const Collection> c,
ref_<const initializer_list<Value_2>> list_2
)
{ return make_multidimensional_view( list_1, c, list_2 ); }
 
template< class Value_1, class Value_2, class Collection >
// iic
inline auto multi(
ref_<const initializer_list<Value_1>> list_1,
ref_<const initializer_list<Value_2>> list_2,
ref_<const Collection> c
)
{ return make_multidimensional_view( list_1, list_2, c ); }
 
template< class Value_1, class Value_2, class Value_3 >
// iii
inline auto multi(
ref_<const initializer_list<Value_1>> list_1,
ref_<const initializer_list<Value_2>> list_2,
ref_<const initializer_list<Value_3>> list_3
)
{ return make_multidimensional_view( list_1, list_2, list_3 ); }
 
How can this be avoided?
 
 
Cheers!,
 
- Alf
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 30 01:44PM +0200

On 30-Mar-17 1:40 PM, Alf P. Steinbach wrote:
> [snip]
 
Sorry about the formatting, the non-aligned comments: it's Thunderbird
messing things up with its flowed format implementation.
 
Cheers!,
 
- Alf
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: