Sunday, February 26, 2017

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

woodbrian77@gmail.com: Feb 26 11:32AM -0800

On Tuesday, January 3, 2017 at 9:11:27 PM UTC-6, Daniel wrote:
 
> If I could make one suggestion, it would be to include some information in
> the site's readme file about what this thing is and why anybody would want to
> use it
 
 
I wrote a Readme with several lines in it:
https://github.com/Ebenezer-group/onwards/blob/master/example/Readme
 
I'm going to take a documentation break for a while.
 
 
Brian
Ebenezer Enterprises
http://webEbenezer.net
thebtc@hotmail.com: Feb 26 10:07AM -0800

@Paavo- yes, you are totally right. I was being careless and wasn't typing the correct commands in.
 
@Ben- I agree, your code is much more elegant than mine. I might go back and change things later, I'm not sure. I'm just a bit apprehensive because my prof for the course loves any possible reason to take off more marks...
 
I'm back to the same problem as before- I'm getting rubbish being printed to my textfile. Here is my updated code:
 
 
#include <iostream>
#include <fstream>
#include "lapacke.h"
 
using namespace std;
 
// allocate space for function LAPACKE_ssyev
extern lapack_int LAPACKE_ssyev(int* matrix_layout, char* jobz, char* uplo, const lapack_int* n,
float* a, const lapack_int* lda, float* w);
 
int main(){
// list the declarations
int matrix_layout = LAPACK_COL_MAJOR; // store arrays in column major
char jobz = 'N'; // computes eigenvalues only
char uplo = 'U'; // stores the upper triangle of a in an array a
const lapack_int n = 10; // the order of the matrix a
float a[n][n] = {
{1, 11, 7, 9, 7, 11, 7, 9, 2, 11},
{11, 4, 10, 10, 6, 2, 9, 6, 10, 0},
{7, 10, 3, 5, 4, 4, 4, 4, 6, 10,},
{9, 10, 5, 3, 8, 8, 3, 5, 1, 8,},
{7, 6, 4, 8, 8, 10, 5, 6, 10, 0},
{11, 2, 4, 8, 10, 9, 4, 3, 5, 11},
{7, 9, 4, 3, 5, 4, 3, 10, 7, 2},
{9, 6, 4, 5, 6, 3, 10, 11, 1, 7},
{2, 10, 6, 1, 10, 5, 7, 1, 10, 5},
{11, 0, 10, 8, 0, 11, 2, 7, 5, 1}
}; // the symmetric matrix a for which the eigenvalues will be found
const lapack_int lda = n; // the leading dimension of the array a
float w[n]; // stores the eigenvalues
 
// open output file
ofstream fout("eigenvaluesA.txt");
 
// compute the eigenvalues; function returns 0 if successful
if (LAPACKE_ssyev(matrix_layout, jobz, uplo, n, &(a[0][0]), lda, w) == 0){
int i;
for (i = 0; i < n; i++);
// print the eigenvalues
fout << w[i] << endl;
};
// close file
fout.close();
 
return 0;
};
 
 
I'm not sure what the issue is with the printing. I also *have* to print my results to a textfile, that's the requirement. It seems to me I'm doing everything right so why isn't it printing? I'm getting "3.54082e-35" and that's it.
Paul <pepstein5@gmail.com>: Feb 26 04:11AM -0800

The following code outputs 1 2 2.
I wouldn't have expected this.
1 1 1 seems to make more sense.
Also 1 2 3 would be my second guess.
Apparently the explanation has to do with "stateful function objects"
but I don't understand what this means.
 
Can anyone explain?
 
Thanks a lot.
 
Paul
 
 
int main()
{int x = 0;
auto foo = [=] () mutable {
 
x++;
 
return x;
};
 
std::cout << foo() << " ";
auto bar = foo;
 
std::cout << foo() << " ";
 
 
std::cout << bar() << " ";
}
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 26 01:19PM +0100

On 26.02.2017 13:11, Paul wrote:
 
> std::cout << foo() << " ";
 
> std::cout << bar() << " ";
> }
 
First call of foo increments its x to 1 and returns that.
 
Copying foo to bar copies the 1.
 
Second call to foo increments its x to 2 and returns that.
 
First call of bar increments its x to 2 and returns that.
 
Not sure how you could think anything else could make sense?
 
 
Cheers & hth.,
 
- Alf
Paul <pepstein5@gmail.com>: Feb 26 04:39AM -0800

On Sunday, February 26, 2017 at 12:21:03 PM UTC, Alf P. Steinbach wrote:
 
> Second call to foo increments its x to 2 and returns that.
 
> First call of bar increments its x to 2 and returns that.
 
> Not sure how you could think anything else could make sense?
 
I still don't get it. In what sense does foo contain an x?
Many people clearly think (erroneously) like me since this
code features in a multiple choice quiz with several options.
 
If the right output was obvious to everyone, no one would
design such a quiz.
 
For example, no one would write a c++ quiz question such as the below:
 
int main()
{
std::cout << 2;
}
 
Which of these is printed by the above code?
 
A) -3000000000
B) 2
C) Hello World
D) 34134343434343
 
Paul
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 26 01:52PM +0100

On 26.02.2017 13:39, Paul wrote:
 
>> First call of bar increments its x to 2 and returns that.
 
>> Not sure how you could think anything else could make sense?
 
> I still don't get it. In what sense does foo contain an x?
 
In the sense of actually containing an x.
 
You can rewrite the lambda as a class:
 
class Foo_lambda
{
private:
int x;
public:
auto operator()()
-> int
{
x++;
return x;
}
 
Foo_lambda( const int x_value )
: x{ x_value }
{}
};
 
The lambda expression produces an instance of this class, or of a class
pretty much like it.
 
That instance contains a data member called `x`, which due to the `=`
capture by value, the constructor initializes with the value of the
outer scope's `x`.
 
If you had not declared the lambda `mutable` then the `operator()` would
effectively have been `const` and couldn't have modified the data
member. I write "effectively" because I don't know the details of the
rules, and e.g. modification of `this` is prevented by treating it as an
rvalue expression instead of treating it as `const`. But whatever the
standard's formal mechanism is, `const` or rvalue or whatever, without
C++17 `mutable` you're prevented from modifying.
 
 
Cheers & hth.,
 
- Alf
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Feb 26 02:26PM

On Sun, 26 Feb 2017 04:39:26 -0800 (PST)
 
> I still don't get it. In what sense does foo contain an x?
> Many people clearly think (erroneously) like me since this
> code features in a multiple choice quiz with several options.
 
I would be surprised if many people think like you. This is a standard
lexical closure and most people will have come across them in python or
javascript (which acquired them from the functional languages) if not
via C++. You might want to look up closures on wikipedia. They can be
confusing to begin with but they have become ubiquitous.
 
In C++, lambda functions are a function object and the closure is
effected via its capture list. In terms of implementation, in C++ the
function object keeps the variables in its lexical environment which
feature in the capture list as private members of the function object.
You will find that C++ has its quirks, particularly about the way a
lambda expression in a non-static member function captures a datum which
is a member of the class - in effect, by default it takes it by
reference, by capturing the 'this' pointer. For such a case, the
default behaviour would result in you getting the "1 2 3" which was your
second expectation, and _that_ is what normally surprises and confuses
newcomers.
Paavo Helde <myfirstname@osa.pri.ee>: Feb 26 04:28PM +0200

On 26.02.2017 14:11, Paul wrote:
 
> int main()
> {int x = 0;
> auto foo = [=] () mutable {
 
Here, you need to change [=] to [&] in order to get the 1 2 3 output. HTH.
 
 
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Feb 26 02:58PM

On Sun, 26 Feb 2017 14:26:09 +0000
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
[snip]
> default behaviour would result in you getting the "1 2 3" which was
> your second expectation, and _that_ is what normally surprises and
> confuses newcomers.
 
It might be worth my making the additional point that you got "1 2 2"
because in C++ objects are copied by value, and that includes function
objects. This means that the captured variables held by the lambda
function object are also copied by value when you copied the lambda.
Languages in which objects (including functions) are copied by
reference, such as javascript, will give "1 2 3". As another poster
has already pointed out, you would get a similar effect in C++ if you
captured the variables concerned by reference rather than by value.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Feb 26 03:23PM

> javascript (which acquired them from the functional languages) if not
> via C++. You might want to look up closures on wikipedia. They can be
> confusing to begin with but they have become ubiquitous.
 
I think it's a stretch to call this a standard lexical closure. Whilst
the lambda part itself looks pretty standard., C++'s lambdas are
peculiar in they can capture objects in the environment by copying, and
these copies objectare a copied on assignment. That is perfectly
natural in the context of C++, but you can't easily write that in the
other languages you cite.
 
> default behaviour would result in you getting the "1 2 3" which was your
> second expectation, and _that_ is what normally surprises and confuses
> newcomers.
 
I have little experience anymore of what surprises newcomers, but 1 2 3
is what you get from writing the seemingly equivalent code in
ECMAScript:
 
var x = 0;
var foo = function () { x++; return x; };
console.log(foo());
var bar = foo;
console.log(foo());
console.log(bar());
 
If you try to emulate the "capture by copying" that [=] is doing in C++
you get 1 1 1:
 
var x = 0;
var foo = function () { var lx = x; lx++; return lx; };
console.log(foo());
var bar = foo;
console.log(foo());
console.log(bar());
 
And now you are stuck because there is no obvious way to get the
assignment of bar to copy the local variable lx 'inside' foo.
 
Python is slightly less help as a model of what C++ is doing because you
can't even write x += 1; return x in a lambda. You can write a function
returning function but you might as well just name foo directly:
 
x = 0;
def foo(): x += 1; return x
print(foo())
bar = foo
print(foo())
print(bar())
 
This gives a run-time error because x is referenced before being
assigned. You have to either state that you want the global one:
 
x = 0;
def foo(): global x; x += 1; return x
print(foo())
bar = foo
print(foo())
print(bar())
 
(giving 1 2 3) or you need to copy x and you go back to getting 1 1 1:
 
x = 0;
def foo(): lx = x; lx += 1; return lx
print(foo())
bar = foo
print(foo())
print(bar())
 
In short, experience of other languages with mutable state and function
values will not help much in understanding the C++ code in the question.
 
--
Ben.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Feb 26 05:12PM

On Sun, 26 Feb 2017 15:23:50 +0000
> copying, and these copies objectare a copied on assignment. That is
> perfectly natural in the context of C++, but you can't easily write
> that in the other languages you cite.
 
I don't agree. A lexical closure is exactly what it is. The main
distinguishing feature of C++ is that the free variables do not
automatically close over the entire lexical environment: they must be
specified in the capture list (which can of course be made to close
over the entire environment with '=').
 
Closures work by copying the captured variables, because they outlast
the lifetime of the surrounding environment (and which is why
overriding this by capturing free variables by reference in C++ is so
dangerous). What is meant by "copy" depends on the language.
Javascript for example copies simple numbers by value, and arrays,
objects and functions by reference (strings are immutable so there is
no difference), and most garbage collected languages do something
similar.
 
> In short, experience of other languages with mutable state and
> function values will not help much in understanding the C++ code in
> the question.
 
The important issue for a learner to understand is how free variables
in lambdas capture their lexical environment.
 
After that, the differences in behavior when copying the lambda (and how
often do you do that?) stem only from whether the lambda object, and
any free variables, are copied by reference or by value; this
difference being prompted in part by C++'s lifetime rules for automatic
objects. Copy by reference of lambda function objects can trivially
be implemented in C++ in the OP's code by changing 'auto bar = foo;' to
'auto& bar = foo;', which would then print "1 2 3".
 
The reverse (copying functions by value) in javascript would require
cloning the function object and all its captured variables. Java (as
opposed to javascript) and python do not permit mutation of free
variables at all. But all these different languages work, with C++, by
lexical closure by free variables.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 26 01:07AM +0100

<url: https://github.com/alf-p-steinbach/Expressive-Cpp>
 
Expressive C++ is a header only library. It implements a less unsafe,
more convenient and readable-for-non-C++-expert-folks dialect of C++. To
do this it depends on the following language extensions, which are
supported by g++, Visual C++ and CLang, and probably also by far more
compilers: • `__COUNTER__`, • `#pragma once`, • `#pragma push_macro`, •
`#pragma pop_macro`, and • use of the `$` character in identifiers.
 
The shortest possible Expressive C++ program is
 
$just{}
 
which is • shorter than a standard `main`, and • safer than a standard
`main` ¹in the case of an exception being thrown out of it, and more •
directly readable, without distracting bits such as the `int` in
 
int main(){}
 
And this is the general philosophy: ²not always shorter like here, but
safer and to the non-expert more directly readable, and generally more
convenient than the raw C++ that Expressive C++ code translates to.
 
Flavor ³example:
 
#include <p/expressive/use_weakly_all.hpp>
#include <iostream>
#include <vector> // std::vector
#include <string> // std::string
$use_weakly_all_from( std );
 
void cpp_main( ref_<const vector<string>> args )
{
for( $each arg $in enumerated( args ) )
cout << "Arg " << arg.index() << " is '" << arg.object() <<
"'.\n";
}
 
$start_with_ascii_arguments( cpp_main )
 
The `ref_` type builder, and others like it, allows one to use the
principle of substitution to construct types, as in non-C languages in
general. It also supports the practice of putting `const` first, even in
nested parts. The resulting type specifications can be naturally read in
the forward direction, unlike in raw C and C++.
 
The $ words like $each and $in above, are pseudo keywords, keywords for
the Expressive C++ dialect, implemented as macros. Expressive C++ also
offers some stuff implemented with ordinary C++ code, using C++ core
language features up to and including C++14. For example, the expression
 
$invoked{ $var x=1; while( x*x < 50 ) ++x; return x - 1; }
 
… uses an Expressive C++ pseudo keyword macro, `$invoked`, to produce a
lambda, and to pass it to some ordinary C++14 machinery that invokes
that lambda and produces its return value with the type implied by the
return statement – which e.g., as here, allows a loop in an expression.
 
Enjoy, even though this is just a version 0.3-or-something.
 
 
- Alf
 
Notes:
¹ If any statements are added, then unlike a raw `main` any exception
out of the `$just` block is caught and reported on the standard error
stream, with guaranteed stack rewinding/cleanup, and a suitable process
exit code that adheres to the OS conventions is produced.
² I've not yet found a good way to express the `:?` operator within the
limits of a macro approach.
³ Sorry about the limitation to "ascii" here. Implementing portable
Unicode command line support, which raw C++ `main` doesn't offer for
systems other than *nix, is much work, and I haven't got to that yet.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Feb 26 03:29AM

On 26/02/2017 00:07, Alf P. Steinbach wrote:
> ³ Sorry about the limitation to "ascii" here. Implementing portable
> Unicode command line support, which raw C++ `main` doesn't offer for
> systems other than *nix, is much work, and I haven't got to that yet.
 
Use of dollar sign ($) in identifiers is implementation defined as to
whether it works so is unportable and should be avoided.
 
/Flibble
Marcel Mueller <news.5.maazl@spamgourmet.org>: Feb 26 02:30PM +0100

On 26.02.17 01.07, Alf P. Steinbach wrote:
> supported by g++, Visual C++ and CLang, and probably also by far more
> compilers: • `__COUNTER__`, • `#pragma once`, • `#pragma push_macro`, •
> `#pragma pop_macro`, and • use of the `$` character in identifiers.
 
I did not get why making the code look as ugly as Perl/php/PowerShell
sould be desirable.
Readability and maintainability does not generally benefit from magic
behind the scenes. Things may get even worse regarding compiler error
messages.
 
 
Marcel
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 26 02:52PM +0100

On 26.02.2017 14:30, Marcel Mueller wrote:
>> compilers: • `__COUNTER__`, • `#pragma once`, • `#pragma push_macro`, •
>> `#pragma pop_macro`, and • use of the `$` character in identifiers.
 
> I did not get [it]
[snip]
 
 
I've started on tutorial-like documentation:
 
<url:
https://github.com/alf-p-steinbach/Expressive-Cpp/blob/master/README.md>
 
I think reading that might help to start clear things up, at least when
one keeps in mind that the rest of the library is similarly justified by
very real problems with raw C++, especially for beginners.
 
One needs to be aware of the shortcomings etc. that are addressed,
before one can understand the advantages and trade-offs, and I hope that
the docs I've started on do communicate this in a good way. :)
 
 
Cheers & hth.,
 
- Alf
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Feb 26 02:28PM

On 26/02/2017 13:52, Alf P. Steinbach wrote:
 
> One needs to be aware of the shortcomings etc. that are addressed,
> before one can understand the advantages and trade-offs, and I hope that
> the docs I've started on do communicate this in a good way. :)
 
This library attempts to solve a problem that doesn't actually exist.
At its best it is simply obfuscation and at its worst it is plain
fucktardary. This library SERVES NO PURPOSE AT ALL.
 
/Flibble
"Chris M. Thomasson" <invalid@invalid.invalid>: Feb 25 07:46PM -0800

On 2/25/2017 6:38 AM, Öö Tiib wrote:
>> which is the other part of that un-sharing-of-buffer operation.
 
> How recently you have profiled that? The lock-free atomic thingies seem
> more expensive than good old mutexes in multiprocessor systems in my tests.
 
A lot of lock-free techniques are way to expensive, and require too many
damn atomics and/or membars to get the job done.
 
A typical generic mutex usually needs two atomic ops and an
acquire/release membar paired relationship to keep the protected data
visible. If a lock free technique needs more membars atomics than its
mutex counterpart, then you are not going to really see a performance
enhancement wrt mutex never hitting its slowpath, blocking. However,
mutexs can block, and that can ruin their performance. Use locking
patterns wisely; Deadlock no more...
 
There are asymmetric locks, and non-blocking algorithms, but they are
more exotic.
 
;^)
 
 
Now, try to beat this sucker with a mutex based queue in a high
pressure, loaded environment. Stress the queue out to see what happens.
 
https://groups.google.com/d/topic/lock-free/acjQ3-89abE/discussion
 
You can use the original CAS based version by Dmitry Vyukov.
 
Or, my fast-pathed wait-free alteration:
 
<pseudo code, membars aside for a moment>
______________________________________________
struct cell { uint32_t ver; double state; };
 
uint32_t head = 0;
uint32_t tail = 0;
cell cells[N]; // N must be a power of 2
 
void init() {
for (uint32_t i = 0; i < N; ++i) cells[i].ver = i;
}
 
void producer(double state) {
uint32_t ver = XADD(&head, 1);
cell& c = cells[ver & (N - 1)];
while (LOAD(&c.ver) != ver) backoff();
c.state = state;
STORE(&c.ver, ver + 1);
}
 
double consumer() {
uint32_t ver = XADD(&tail, 1);
cell& c = cells[ver & (N - 1)];
while (LOAD(&c.ver) != ver + 1) backoff();
double state = c.state;
STORE(&c.ver, ver + N);
return state;
}
______________________________________________
 
Keep in mind, the tweak is wait-free on the atomics when fetch-and-add
is hardware based, and has no loops, like most CAS and/or all LL/SC.
Keep in mind that LOCK XADD is an example of a wait-free op, vs using
CMPXCHG in a software based loop on Intel...
 
Now, I also have a version of this with conditional waits here:
 
https://groups.google.com/forum/#!original/lock-free/acjQ3-89abE/idSNj77HsIIJ
JiiPee <no@notvalid.com>: Feb 26 10:15AM

On 24/02/2017 23:28, Alf P. Steinbach wrote:
> E.g. by simply not sharing mutable objects between threads.
 
 
or doing mutex....
Marcel Mueller <news.5.maazl@spamgourmet.org>: Feb 26 11:57AM +0100

On 25.02.17 00.28, Alf P. Steinbach wrote:
>> is not too good idea most of the time.
 
> Uhm, thread safety is an orthogonal issue. Adding illusory thread safety
> to a string class is going to cost, no matter the internal implementation.
 
True.
 
A work around is to make only volatile instances thread safe. And of
course, this instances do not provide all operations.
(Of course, this is some kind of abuse of the volatile keyword.)
 
> threads, it would be impractical to lock down the object any time its
> `operator[]` returns a reference that possibly could be stored by the
> thread and used to modify the string at arbitrary times.
 
There are some operations where thread safety makes no sense at all.
Probably no one expects a single mutable string instance to be thread
safe at any modifications.
 
But when using CoW or deduplication another thread issues arises since
now different string instances may share the same data. And of course,
the programmer expects the instance methods of his own instance to
require no global lock.
 
In fact it is a good advice to separate mutable strings from immutable
strings like Java or .NET do. (StringBuffer/Builder vs. String)
The C++ string class unfortunately represents the mutable version. So
introducing a immutable string class is a breaking change for many APIs.
And no performance benefit arises when the efficient immutable class is
converted to std::string all the time.
However, in any larger program where I could control all the APIs I have
done this job - with reasonable success. This concept is superior to CoW
since the copy operations are now visible part of the type system. In
practice this rarely happens at all since the use cases for mutable and
immutable strings are quite different.
 
 
> fine, I think. It's the responsibility of the code that uses those
> classes, to ensure thread safe operation. E.g. by simply not sharing
> mutable objects between threads.
 
Ack. But this does not apply to objects that are shared internally like
with CoW, since the programmer typically can't control this with
reasonable effort.
 
 
Marcel
bitrex <bitrex@de.lete.earthlink.net>: Feb 25 06:38PM -0500

Say I have a class, call it Bitmap, which holds onto a texture resource,
say "my_bitmap.png" which has to be allocated and deallocated through a
constructor and destructor the "old-fashioned" way via new and delete.
 
I then want to stick this class in a wrapper class that can be used as a
key-value type for boost::flyweight, using a smart pointer to wrap the
Bitmap class so that all objects in a graphics program that use
"my_bitmap.png" can refer to the one instance, and when all objects that
use it are destroyed the resource is release.
 
Is it more appropriate to use a std::unique_ptr or a std::shared_ptr in
the wrapper class in this circumstance?
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 26 01:09AM +0100

On 26.02.2017 00:38, bitrex wrote:
> use it are destroyed the resource is release.
 
> Is it more appropriate to use a std::unique_ptr or a std::shared_ptr in
> the wrapper class in this circumstance?
 
`std::shared_ptr` implements shared ownership, while `std::unique_ptr`
implements single but transferable ownership.
 
So ask yourself: do I have a case of shared ownership, or do I have a
case of transferable single ownership?
 
Or do I have something else, like e.g. automatic cloning on copy?
 
 
Cheers & hth.,
 
- Alf
bitrex <bitrex@de.lete.earthlink.net>: Feb 25 07:35PM -0500

On 02/25/2017 07:09 PM, Alf P. Steinbach wrote:
 
> Or do I have something else, like e.g. automatic cloning on copy?
 
> Cheers & hth.,
 
> - Alf
 
Indeed, my point of confusion is about how boost::flyweight is operating
internally.
 
Instead of looking at the source right now (what a silly idea!) I'll
instead just randomly speculate that the flyweight type is itself
creating a wrapper type which holds a shared reference, and each time a
new class is created with a key that hashes to the same value type it
makes a new wrapper and clones the reference, rather than call the
copy/move constructor on my own.
 
So I'd guess that I'd want to use a unique_ptr for the resource in my
wrapper, as at the end of the day all flyweights that hash to an
instance of it are finally all referring to the same resource. When all
the flyweights are gone the pointer to my wrapper is released, and along
with it goes the unique_ptr contained within.
woodbrian77@gmail.com: Feb 25 07:19PM -0800

On Saturday, February 25, 2017 at 6:36:35 PM UTC-6, bitrex wrote:
> instance of it are finally all referring to the same resource. When all
> the flyweights are gone the pointer to my wrapper is released, and along
> with it goes the unique_ptr contained within.
 
I would start with unique_ptr since it's simpler than shared_ptr.
If you find later that shared_ptr would be helpful, you can switch
to that.
 
 
Brian
Ebenezer Enterprises
http://webEbenezer.net
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Feb 26 01:50AM +0100

On 24.02.2017 21:08, Tim Rentsch wrote:
> stuff. To look at any code more than about 10 or 20
> lines I would like to be able to compile it. If the
> code is written in "expressive" C++ I can't do that.
 
I've posted the current version of Expressive C++ on GitHub:
 
<url: https://github.com/alf-p-steinbach/Expressive-Cpp>
 
It uses a really tiny macro library, Macro Magic, that I also posted:
 
<url: https://github.com/alf-p-steinbach/Macro-Magic/>
 
Both libraries are header only and designed to be placed in a common `p`
directory in the compiler's include path. `p` is my middle name
shortened to one letter, and it's also short for "progrock".
 
Not sure exactly where to take this but it fills my free time.
 
And considering that you offered (if memory serves me!), I would be very
grateful if you could take over the balanced tree tutorial.
 
Another reason for that, if you have time, is that you evidently are
familiar with the subject, knowing stuff that I didn't know. ;-)
 
 
Cheers!,
 
- Alf
woodbrian77@gmail.com: Feb 25 03:13PM -0800

On Friday, February 24, 2017 at 2:19:15 PM UTC-6, Tim Rentsch wrote:
> otherwise. From the author's point of view, the page being
> posted is pretty much all free advertsing, with negligible
> downside.
 
Authors and publishers often give free access to a few pages
of their books. An individual giving away additional pages
is making a higher percentage of the book available for free.
Some people won't buy the cow when they can get the milk for free.
 
http://nypost.com/2017/02/24/150k-supercar-stolen-during-test-drive/
 
At some point, the higher percentage that's free the less likely
people are to pay for it. I'm thankful I don't need to make a
living as a traditional author.
 
 
Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net
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: