Monday, July 17, 2017

Digest for comp.lang.c++@googlegroups.com - 11 updates in 3 topics

woodbrian77@gmail.com: Jul 16 09:05PM -0700

> C++ Middleware Writer. If you have some thoughts on
> how to improve the software or documentation on my
> site, please let me know.
 
 
I've been working on the documentation here:
 
http://webEbenezer.net/middle.html
 
. In particular, I've added a new option that, for now,
is called yea_nay. What it does it facilitate turning
these two generated functions:
 
inline void Marshal (::cmw::SendBuffer& buf
,bool az1){
try{
buf.ReserveBytes(4);
buf.Receive(az1);
buf.FillInSize(cmw::udp_packet_max);
}catch(...){buf.Rollback();throw;}
}
 
void Marshal (::cmw::SendBuffer& buf
,bool az1
,cmw::string_plus const& az2){
try{
buf.ReserveBytes(4);
buf.Receive(az1);
az2.Marshal(buf);
buf.FillInSize(cmw::udp_packet_max);
}catch(...){buf.Rollback();throw;}
}
 
into one function:
 
void Marshal (::cmw::SendBuffer& buf
,bool az1
,cmw::string_plus const& az2={}){
try{
buf.ReserveBytes(4);
buf.Receive(az1);
if(az1)goto rtn;
az2.Marshal(buf);
rtn:
buf.FillInSize(cmw::udp_packet_max);
}catch(...){buf.Rollback();throw;}
}
 
Here's the documentation from the page I linked to
above on this new feature:
 
The yea_nay option is used to support a common messaging idiom
where a response to a request is a bool followed by optional data.
Rather than having two messages like this:
 
-out (bool)
-out (bool, cmw::string_plus)
 
, the following can be used:
 
-out -yea_nay (bool, cmw::string_plus)
 
. When yea_nay is used, the object(s) after the bool are
only used if the value of the bool is false. This option
leads to less output from the CMW and smaller executable sizes.
--------------------------------------------------------
I simplified the Middle code above in an effort to make it
easier to understand. The real code is like this:
 
-out -max_length=cmw::udp_packet_max (bool)
-out -max_length=cmw::udp_packet_max -no_inline (bool,cmw::string_plus)
 
 
-out -max_length=cmw::udp_packet_max -no_inline -yea_nay (bool,cmw::string_plus)
 
 
Brian
Ebenezer Enterprises - Enjoying programming again.
http://webEbenezer.net
woodbrian77@gmail.com: Jul 16 09:30PM -0700


> -out -yea_nay (bool, cmw::string_plus)
 
> . When yea_nay is used, the object(s) after the bool are
> only used if the value of the bool is false.
 
I decided to change the word "used" to "marshalled."
 
 
Brian
Ebenezer Enterprises
http://webEbenezer.net
Christian Gollwitzer <auriocus@gmx.de>: Jul 17 07:30AM +0200


> -out -yea_nay (bool, cmw::string_plus)
 
> . When yea_nay is used, the object(s) after the bool are
> only used if the value of the bool is false.
 
You might reconsider the naming of it (and also the true/false
semantics). Such a data type is commonly called Maybe, Nullable, or Option:
 
https://en.wikipedia.org/wiki/Option_type
 
Even C++17 has it as std::optional<T> according to that list.
 
Christian
woodbrian77@gmail.com: Jul 17 07:09AM -0700

On Monday, July 17, 2017 at 12:30:25 AM UTC-5, Christian Gollwitzer wrote:
 
> > . When yea_nay is used, the object(s) after the bool are
> > only used if the value of the bool is false.
 
> You might reconsider the naming of it
 
Sure.
 
> semantics). Such a data type is commonly called Maybe, Nullable, or Option:
 
> https://en.wikipedia.org/wiki/Option_type
 
> Even C++17 has it as std::optional<T> according to that list.
 
I'm willing to add support for std::optional if someone
wants that, but for me, what I have makes it clearer
what's happening from a messaging perspective.
 
 
Brian
Ebenezer Enterprises - so far G-d has helped us.
http://webEbenezer.net
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jul 17 06:50PM +0100


> I'm willing to add support for std::optional if someone
> wants that, but for me, what I have makes it clearer
> what's happening from a messaging perspective.
 
If bool is false is the associated data object still default
constructed? If so your alternative to optional is inferior as well as
uglier.
 
/Flibble
woodbrian77@gmail.com: Jul 17 03:24PM -0700

On Monday, July 17, 2017 at 12:51:00 PM UTC-5, Mr Flibble wrote:
> > what's happening from a messaging perspective.
 
> If bool is false is the associated data object still default
> constructed?
 
If the bool is true, the associated object is default constructed.[1]
I'm not sure how the two approaches compare at runtime, but in
one application the approach using yea_nay reduces the size of
the executable by 68 bytes. In another app it reduces the size
by 16 bytes. I believe the cost of the default construction is
very little -- at least in this case.
 
> If so your alternative to optional is inferior as well as
> uglier.
 
I'm not working on an alternative to optional.
 
 
[1] The context is a response to a request has arrived.
A value of 'true' for the bool means the request was
successful and there's nothing more to the message. A
value of 'false' for the bool means the request failed
and there's more info in the message.
 
I don't claim this works for all requests, but in a lot of
cases it's sufficient.
 
 
Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net
rep_movsd <rep.movsd@gmail.com>: Jul 17 06:43AM -0700

I'm writing a library that does compile time parsing, creating a list.
The only way I am able to get it to work right now is by using a std::array of my Node structure as a "statically allocated pool" and using integer indexes as "pointers" into that array.
 
This works great, but I am forced to fix the size of the array.
 
Here is what I have:
 
#include <iostream>
using namespace std;
 
struct Symbol
{
constexpr Symbol(): pBeg(), pEnd() {}
constexpr Symbol(const char *pBeg, const char *pEnd): pBeg(pBeg), pEnd(pEnd) {}
constexpr int len() { return pEnd - pBeg; }

string getText() const { return string(pBeg, pEnd); }


const char *pBeg;
const char *pEnd;
};
 
 
extern void ParseError(const char *s) {cerr << "Parse Error:" << s << endl;}
 
constexpr bool isAlpha(char ch)
{
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
}
 
// Raises compiletime error if no more characters left to parse
constexpr const char *checkEOS(const char *pszText)
{
bool eos = !*pszText;
if(eos) ParseError("Unexpected end of stream");

return pszText;
}
 
// Takes a string literal and returns pointer to first non-whitespace character
constexpr const char *eatSpace(const char *pszText)
{
while(*pszText == ' ' || *pszText == '\n' || *pszText == '\r' || *pszText == '\t')
{
++pszText;
}
return pszText;
}
 
// Takes a string literal text and tries to consume [a-z]+
constexpr const Symbol eatAlpha(const char *pszText)
{
// Ensure not EOS
checkEOS(pszText);

Symbol sym;
sym.pBeg = pszText;
sym.pEnd = pszText;
while(isAlpha(*sym.pEnd)) sym.pEnd++;

// Ensure at least 1 character is consumed
bool empty_tag = sym.pBeg == sym.pEnd;
if(empty_tag) ParseError("Expecting an identifier");

return sym;
}
 
struct Node
{
Symbol tag; // pointer to tag name range
const Node &child;

constexpr Node(Symbol tag, const Node child):tag(tag), child(child){}

};
 
constexpr const Symbol NullSym;
constexpr const Node NullNode{NullSym, NullNode};
 
 
constexpr Node parse(const char* text)
{
if(text)
{
text = eatSpace(text);
if(isAlpha(*text))
{
Symbol symTag = eatAlpha(text);
return Node(symTag, parse(symTag.pEnd));
}
}
return NullNode;
}
 
void dumpNode(const Node &n, int indent = 0)
{
if(&n.child != &NullNode)
{
cerr << n.tag.getText() << endl;
dumpNode(n.child, indent + 1);
}
}
 
 
int main()
{
constexpr Node node = parse("attr battr cattr");
dumpNode(node);
}
 
When compiling:
 
$ g++ --std=c++14 -DSPT_DEBU main4.cpp
main4.cpp:72:48: error: 'Node{Symbol{0, 0}, child}' is not a constant expression
constexpr const Node NullNode{NullSym, NullNode};
^
main4.cpp: In function 'int main()':
main4.cpp:101:49: in constexpr expansion of 'parse(((const char*)"attr battr cattr"))'
main4.cpp:83:44: in constexpr expansion of 'parse(symTag.Symbol::pEnd)'
main4.cpp:83:44: in constexpr expansion of 'parse(symTag.Symbol::pEnd)'
main4.cpp:83:44: in constexpr expansion of 'parse(symTag.Symbol::pEnd)'
main4.cpp:101:49: error: constexpr call flows off the end of the function
constexpr Node node = parse("attr battr cattr");
^
 
Is what I am trying even possible?
 
I'm a bit hazy about what the lifetime of constexpr values are when you nest them through recursive calls
 
I'm pretty sure this should be possible. After all someone wrote a constexpr C compiler.
 
All I need is some sort of dynamic data structure like a list, that doesnt have to be fixed in size at compile time.
 
Thanks in advance.
"Öö Tiib" <ootiib@hot.ee>: Jul 17 10:30AM -0700

On Monday, 17 July 2017 16:44:01 UTC+3, rep_movsd wrote:
> of my Node structure as a "statically allocated pool" and using
> integer indexes as "pointers" into that array.
 
> This works great, but I am forced to fix the size of the array.
 
Might be worthy exercise but further posted code does not quite reflect what
you wrote above.
 
 
> };
 
> constexpr const Symbol NullSym;
> constexpr const Node NullNode{NullSym, NullNode};
 
You plan to pass a copy of NullNode to its own constructor? Creating such
constexpr temporaries and taking references to those won't work.
 
> {
> Symbol symTag = eatAlpha(text);
> return Node(symTag, parse(symTag.pEnd));
 
Again same thing as on previous case but this time recursive return values
passed by value and then taken references. :D
 
 
> Is what I am trying even possible?
 
> I'm a bit hazy about what the lifetime of constexpr values are when you
> nest them through recursive calls
 
Do not try to build your list into some sort of references taken to
by-value returns of functions or by-value passed function parameters.
That is not meant to work.
 
 
> All I need is some sort of dynamic data structure like a list, that
> doesnt have to be fixed in size at compile time.
 
> Thanks in advance.
 
Sure it is possible but it is strange how you try it.
 
First thing get rid of pointer algebra. Length of string literal is
known to compiler so pass around the reference to it like that:
 
#include <iostream>
 
template<size_t N> constexpr
size_t len(char const (&literal)[N])
{
return N;
}
 
template<size_t N> constexpr
char nth_char(char const (&literal)[N], size_t n)
{
return literal[n];
}
 
int main()
{
constexpr char what_we_parse[] = "attr battr cattr";
constexpr size_t l = len(what_we_parse);
constexpr char c = nth_char(what_we_parse, 5);
std::cout << "Len: " << l << " 5th: " << c << std::endl;
}
 
Try it. It will make your code lot simpler.
rep_movsd <rep.movsd@gmail.com>: Jul 17 11:00AM -0700

On Monday, July 17, 2017 at 11:00:42 PM UTC+5:30, Öö Tiib wrote:
> std::cout << "Len: " << l << " 5th: " << c << std::endl;
> }
 
> Try it. It will make your code lot simpler.
 
I already have a parser working, which takes in a std::array of nodes of fixed size.
As the constexpr function calls itself recursively, it adds nodes to the std:array
 
The only problem with that method is that I need to arbitrarily pre-select a size for the array
 
In actuality I need to parse a LISP cons like data structure (which is a multiway tree), so the statically allocated thing is likely to be limiting.
"Öö Tiib" <ootiib@hot.ee>: Jul 17 12:21PM -0700

On Monday, 17 July 2017 21:00:38 UTC+3, rep_movsd wrote:
> nodes to the std:array
 
> The only problem with that method is that I need to arbitrarily pre-select
> a size for the array
 
Now you lost me. You have input data available so why you can not count
needed size of array instead of randomly selecting something?
 
 
> In actuality I need to parse a LISP cons like data structure (which is
> a multiway tree), so the statically allocated thing is likely to be
> limiting.
 
Huh? Every constexpr variable is *very* static and immutable already at
time of compiling the program. It is *defining* feature of constexpr data
and it is no way limiting it. :D
Lynn McGuire <lynnmcguire5@gmail.com>: Jul 17 11:38AM -0500

"Trip report: Summer ISO C++ standards meeting (Toronto)" by Herb Sutter

https://herbsutter.com/2017/07/15/trip-report-summer-iso-c-standards-meeting-toronto/
 
"This was the first meeting where we could vote changes into Draft
C++20. And we did!"
 
Lynn
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: