[Boost][Proposal] library for enhanced switch syntax. Request for Comments

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

[Boost][Proposal] library for enhanced switch syntax. Request for Comments

Boost - Dev mailing list
Hi All,

I wrote a library *eswitch* which provides enhanced functionality for* C++
switch*.
Please take a look and leave your comments.

*=====================*
*Motivation:*
*=====================*
To overcome "*native switch*" limitations:
- one parameter per "*native switch*"
- the parameter restricted to only *integral *types( int, char, enum ... ).

"*eswitch*" supports any number of parameters and almost without
restriction on their *type*,
as long as the *type *is comparable( i.e. has* operator==* ).



*=====================Why it is important?=====================*

Here is the most viewed questions on the *stackoverflow*:

FEATURE VIEWS
Multiple conditions in switch case
<https://stackoverflow.com/questions/68578/multiple-cases-in-switch-statement>
850k
Switch for string
<https://stackoverflow.com/questions/650162/why-the-switch-statement-cannot-be-applied-on-strings>
693k
Case match in range
<https://stackoverflow.com/questions/9432226/how-do-i-select-a-range-of-values-in-a-switch-statement/24133078#24133078>
133k
Over a million views indicate how many people out there are disappointed
with limited functionality of "*native switch*".
Building parallels with such operators as "*if*"/"*while*"... it is
expected by default that "*native switch*" should have the same
possibilities:

   - be able to work with *non-integral* types as well
   - be able to compose complex conditions like we do in other operators "
   *if*"/"*while*"...

Unfortunately it is not the case up till now.  There was a proposal in
2013 *Relax
switch statement
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3627.html>*, and
committee agreed
about importance of this topic. There also was *StringSwitch
<http://llvm.org/doxygen/classllvm_1_1StringSwitch.html>*
implementation by *LLVM
*and *Case ranges
<https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html>* non-standard
extension which is supported by *gcc*, *intel C/C++* and *clang*.
Nevertheless, we still don't have common and universal solution. People
want to overcome current "*native switch*" limitation either by implementing
their own solution, non-standard extension or even trying to standardize
it.
Making proposed *eswitch <https://github.com/rabdumalikov/eswitch_v4>*
functionality
part of the *Boost-Library *will provide millions of developers useful,
universal and agile functionality in order to finally fulfill their needs.



*=====================repository:=====================*
https://github.com/rabdumalikov/eswitch_v4




*=====================References:=====================/// "switch for
non-integral" on stackoverflow*
1.
https://stackoverflow.com/questions/650162/why-the-switch-statement-cannot-be-applied-on-strings
2.
https://stackoverflow.com/questions/16388510/evaluate-a-string-with-a-switch-in-c
3.
https://stackoverflow.com/questions/5452188/switch-case-statement-in-c-with-a-qstring-type
4.
https://stackoverflow.com/questions/19273092/character-in-switch-statement-c
5. https://stackoverflow.com/questions/4165131/c-c-switch-for-non-integers
6. https://stackoverflow.com/questions/27536575/switch-case-on-char

*/// "Multiple conditions" on stackoverflow*
7.
https://stackoverflow.com/questions/8644096/multiple-conditions-in-switch-case
8.
https://stackoverflow.com/questions/68578/multiple-cases-in-switch-statement

*/// "Ranges in case" on stackoverflow*
9.
https://stackoverflow.com/questions/9432226/how-do-i-select-a-range-of-values-in-a-switch-statement/24133078#24133078

*/// "Case ranges" - non-standard extension*
10. https://gcc.gnu.org/onlinedocs/gcc/Case-Ranges.html

*/// LLVM "StringSwitch"*
11. http://llvm.org/doxygen/classllvm_1_1StringSwitch.html

*/// "Relax switch statement" proposal*
12. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3627.html
*/// "N3627 Relaxed switch statement" c++ committee status*
13. https://cplusplus.github.io/EWG/ewg-active.html


*Best Regards.*

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
[hidden email] wrote:
> I wrote a library *eswitch* which provides enhanced functionality for* C++
> switch*.
> Please take a look and leave your comments.

I've had a look at your docs, and I don't immediately find anything
that explains how it works.

Specifically thinking about strings, there are numerous ways
that it could be done.  Starting with

switch (s) {
  case "aa" : f(); break;
  case "ab" : g(); break;
  case "xy" : h(); break;
}

that can be transformed into:

(1): the obvious sequence of if-else-if:

if      (s == "aa") f();
else if (s == "ab") g();
else if (s == "xy") h();

(2): binary search using nested switches:

switch (s <=> "ab") {
  case -1: switch (s <=> "aa") {
             case -1: break;
             case 0:  f(); break;
             case 1:  break;
           }
           break;
  case 0:  g();
           break;
  case 1:  switch (s <=> "xy") {
             case -1: break;
             case 0:  h(); break;
             case 1:  break;
           }
           break;
}

(3) character-by-character comparison using nested switches:

switch (s[0]) {
  case 'a': switch (s[1]) {
              case 'a': switch (s[2]) {
                          case 0: f(); break;
                        }
              case 'b': switch (s[2]) {
                          case 0: g(); break;
                        }
            }
  case 'x': switch (s[1]) {
              case 'y': switch (s[2]) {
                          case 0: h(); break;
                        }
            }
}

(4) converting to a 64-bit integer, for strings of up to 8 characters:

switch (cast_to_uint64(s)) {
  case "aa"TOINT: f(); break;
  case "ab"TOINT: g(); break;
  case "xy"TOINT: h(); break;
}

(5) hashing, and then checking:

switch (hash(s)) {
  case "aa"HASH: if (s=="aa") f(); break;
  case "ab"HASH: if (s=="ab") g(); break;
  case "xy"HASH: if (s=="xy") h(); break;
}

I'm sure there are other possibilities.


Regarding syntax, there isn't much wrong with just writing the
sequence of if-else-ifs.  In particular, when the next person comes
along and needs to understand this code, which of the following
will they prefer:

if      (s == "aa") f();
else if (s == "ab") g();
else if (s == "xy") h();

or:

eswitch(s) >>
  case_("aa") >> []{ f(); } >>
  case_("ab") >> []{ g(); } >>
  case_("xy") >> []{ h(); };

I can see no benefit to your version, UNLESS it results in a more
efficient implementation than the if-else-if version.


Regards, Phil.



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
Op 10-11-19 om 15:16 schreef Phil Endecott via Boost:
> I can see no benefit to your version, UNLESS it results in a more
> efficient implementation than the if-else-if version.

+1 from me. Point very well illustrated


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Am 10.11.19 um 15:16 schrieb Phil Endecott via Boost:

> Regarding syntax, there isn't much wrong with just writing the
> sequence of if-else-ifs.  In particular, when the next person comes
> along and needs to understand this code, which of the following
> will they prefer:
>
> if      (s == "aa") f();
> else if (s == "ab") g();
> else if (s == "xy") h();
>
> or:
>
> eswitch(s) >>
>    case_("aa") >> []{ f(); } >>
>    case_("ab") >> []{ g(); } >>
>    case_("xy") >> []{ h(); };
>
> I can see no benefit to your version, UNLESS it results in a more
> efficient implementation than the if-else-if version.
Only benefit I see is DRY: The expression to check is only mentioned
once. Think of `s` being `CalcSomeValueBasedOnInput(foo, bar, baz)`. The
proposed switch allows to put that into the switch statement and never
even introduce a variable in the source.

There is benefit in doing so, but I'd rather see this as a language
feature. Make a `switch-case-default` equivalent to `if-elseif-else` by
means of the language and have compiler warning/errors for double cases
(e.g. due to C&P) which you don't have for `if-elseif`.

So my suggestion would be to write a standards proposal and develop the
library solution around it as a PoC.

Alex




_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

smime.p7s (6K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On Sun, 10 Nov 2019 at 14:16, Phil Endecott via Boost
<[hidden email]> wrote:
>
> Specifically thinking about strings, there are numerous ways
> that it could be done.  Starting with

Even for integers there are multiple ways it could be done.
It's up to the compiler to decide what is best.


> (3) character-by-character comparison using nested switches:
>
> switch (s[0]) {
>   case 'a': switch (s[1]) {
>               case 'a': switch (s[2]) {
>                           case 0: f(); break;
>                         }
>               case 'b': switch (s[2]) {
>                           case 0: g(); break;
>                         }
>             }
>   case 'x': switch (s[1]) {
>               case 'y': switch (s[2]) {
>                           case 0: h(); break;
>                         }
>             }
> }

That is probably the "natural" implementation that one would expect.


> (5) hashing, and then checking:
>
> switch (hash(s)) {
>   case "aa"HASH: if (s=="aa") f(); break;
>   case "ab"HASH: if (s=="ab") g(); break;
>   case "xy"HASH: if (s=="xy") h(); break;
> }

That code doesn't really need to check, if your hashes collide the
compiler will reject the code.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
On 11.11.19 10:27, Mathias Gaunard via Boost wrote:

> On Sun, 10 Nov 2019 at 14:16, Phil Endecott via Boost
> <[hidden email]> wrote:
>> switch (hash(s)) {
>>    case "aa"HASH: if (s=="aa") f(); break;
>>    case "ab"HASH: if (s=="ab") g(); break;
>>    case "xy"HASH: if (s=="xy") h(); break;
>> }
>
> That code doesn't really need to check, if your hashes collide the
> compiler will reject the code.

Here 's' could have a value that does not match any of the labels (but
with the same hash as one of the labels), so the code does need to check.


--
Rainer Deyke ([hidden email])


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Mathias Gaunard <[hidden email]> wrote:
> On Sun, 10 Nov 2019 at 14:16, Phil Endecott via Boost
> <[hidden email]> wrote:
>>
>> Specifically thinking about strings, there are numerous ways
>> that it could be done.  Starting with
>
> Even for integers there are multiple ways it could be done.
> It's up to the compiler to decide what is best.

Yes, it's important to remember that anything that converts
to a conventional switch statement (for example, by hashing
the string) then relies on how the compiler chooses to
implement it.  There are probably different implementations
for sparse vs. dense case values, for example.  If the
compiler turns a sparse switch statement into an if-else-if
chain, you might as well have an if-else-if chain in the
first place (in terms of performance).

>> (5) hashing, and then checking:
>>
>> switch (hash(s)) {
>>   case "aa"HASH: if (s=="aa") f(); break;
>>   case "ab"HASH: if (s=="ab") g(); break;
>>   case "xy"HASH: if (s=="xy") h(); break;
>> }
>
> That code doesn't really need to check, if your hashes collide the
> compiler will reject the code.

You need to check if s might not match any of the case labels
but might collide with them.


Regards, Phil.





_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
Phil Endecott wrote:
> If the compiler turns a sparse switch statement into an if-else-if chain,
> you might as well have an if-else-if chain in the first place (in terms of
> performance).

Compilers also turn an if-else chain into a switch:
https://godbolt.org/z/7fgSXH

In fact, I think that LLVM first turns the switch into an if-else chain, and
then back into a switch in a later pass.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
Phil Endecott wrote:

> Specifically thinking about strings, there are numerous ways
> that it could be done. Starting with
> (1): the obvious sequence of if-else-if:
> ...
> (2): binary search using nested switches:
> ...
> (3) character-by-character comparison using nested switches:
> ...
> (4) converting to a 64-bit integer, for strings of up to 8 characters:
> ...

Firstly my implementation was never particularly about string in "switch"
it is just one of the applications.
Secondly, example 3-4 assume additional implementation( can take quite a
time to do it right ), it isn't like you have it out of the box,
this is exactly what my statement was about( example 1-2 don't count, they
are non-scalable ).
Lets rather consider something that is more complex:

-- Example_1 "Parse file by extension":

switch( hash_it( get_file_extention( file_name ) ) )
{
case "cpp"HASH:
case "cc"HASH:
case "c++"HASH:
case "cxx"HASH:
case "C"HASH:
{ ... }
break;
case "hpp"HASH:
case "hh"HASH:
case "h++"HASH:
case "hxx"HASH:
case "H"HASH:
{ ... }
break;
}

// OR

// I think this way it is much readable
eswitch( get_file_extention( file_name ) ) >>
case_( any_from( "cpp", "cc", "c++", "cxx", "C" ) ) >> [&]{...} >>
case_( any_from( "h", "hpp", "hh", "h++", "hxx", "H" ) ) >> [&]{...};

// OR
// even this could be possible( but not yet implemented )
eswitch( get_file_extention( file_name ) ) >>
case_( "cpp", "cc", "c++", "cxx", "C" ) >> [&]{...} >>
case_( "h", "hpp", "hh", "h++", "hxx", "H" ) >> [&]{...};

-- Example_2 "Parse HTTP header with Regex":

// O_o too much boilerplate
    if( std::regex_match( line, "^.+ 200 .+$"_r ) ){...}
else if( std::regex_match( line, "^.+ 404 .+$"_r ) ){...}
else if( std::regex_match( line, "^.+: .+$"_r ) ){...}
else { terminate(); }

// OR

// I think this way your intention is clearer
eswitch( line ) >>
case_( "^.+ 200 .+$"_r ) >> []{...} // match for "HTTP/1.1 200 OK"
case_( "^.+ 404 .+$"_r ) >> []{...} // match for "HTTP/1.1 404 Not Found"
case_( "^.+: .+$"_r )    >> [&]{...} >> // match for "key: value"
default_ >> []{ terminate(); };


-- Example_2 "match in range of values":

// Error prone approach
if( value >=  1 && value <= 10 ){ Print("Value in a range[1,10]"); }
if( value >= 11 && value <= 20 ){ Print("Value in a range[11,20]"); }
else { Print('?'); };

/// OR

eswitch( value ) >>
        case_( _1.in( 1, 10 ) )  >> []{ Print("Value in a range[1,10]"); }
 >>
        case_( _1.in( 11, 20 ) ) >> []{ Print("Value in a range[11,20]"); }
>>
        default_                 >> []{ Print('?'); };
 // _1 it is lazy index mapping for the params in eswitch


I my opinion "eswitch" looks more readable, more intuitive, less error prone
and furthermore it is extensible.

P.S.
Here
https://github.com/rabdumalikov/proposals/blob/master/eswitch_boost_proposal.pdf
I had described why I think it is important( just in case you've missed it
).

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list

> On 11. Nov 2019, at 18:39, рустам абдумаликов via Boost <[hidden email]> wrote:
>
> // I think this way it is much readable
> eswitch( get_file_extention( file_name ) ) >>
> case_( any_from( "cpp", "cc", "c++", "cxx", "C" ) ) >> [&]{...} >>
> case_( any_from( "h", "hpp", "hh", "h++", "hxx", "H" ) ) >> [&]{...};
>
> // OR
> // even this could be possible( but not yet implemented )
> eswitch( get_file_extention( file_name ) ) >>
> case_( "cpp", "cc", "c++", "cxx", "C" ) >> [&]{...} >>
> case_( "h", "hpp", "hh", "h++", "hxx", "H" ) >> [&]{...};
>
> -- Example_2 "Parse HTTP header with Regex":
>
> // O_o too much boilerplate
>    if( std::regex_match( line, "^.+ 200 .+$"_r ) ){...}
> else if( std::regex_match( line, "^.+ 404 .+$"_r ) ){...}
> else if( std::regex_match( line, "^.+: .+$"_r ) ){...}
> else { terminate(); }
>
> // OR
>
> // I think this way your intention is clearer
> eswitch( line ) >>
> case_( "^.+ 200 .+$"_r ) >> []{...} // match for "HTTP/1.1 200 OK"
> case_( "^.+ 404 .+$"_r ) >> []{...} // match for "HTTP/1.1 404 Not Found"
> case_( "^.+: .+$"_r )    >> [&]{...} >> // match for "key: value"
> default_ >> []{ terminate(); };
>
>
> -- Example_2 "match in range of values":
>
> // Error prone approach
> if( value >=  1 && value <= 10 ){ Print("Value in a range[1,10]"); }
> if( value >= 11 && value <= 20 ){ Print("Value in a range[11,20]"); }
> else { Print('?'); };
>
> /// OR
>
> eswitch( value ) >>
>        case_( _1.in( 1, 10 ) )  >> []{ Print("Value in a range[1,10]"); }
>>>
>        case_( _1.in( 11, 20 ) ) >> []{ Print("Value in a range[11,20]"); }
>>>
>        default_                 >> []{ Print('?'); };
> // _1 it is lazy index mapping for the params in eswitch
>
>
> I my opinion "eswitch" looks more readable, more intuitive, less error prone
> and furthermore it is extensible.

I don't like this syntax, it is awkward and making the code less readable.

1) You are replacing a normal switch, which may be limited in its abilities but is well known even to beginners with something that has a rather unintuitive syntax. The shift operators are associated to streaming in C++ these days, but you use them differently here. Someone who reads this code who is not familiar with eswitch will not immediately understand this. Why did you chose operator>> instead of operator<< ? I think the choice is arbitrary and therefore hard to remember.

2) Your syntax requires one to type a lot of characters. I don't think one should replace the switch but if one did, the following syntax would be more economic and easier to remember, because it is less arbitrary

eswitch( value, case(match1), lambda1, case(match2), lambda2 , … , default(), lambdaN );

Best regards,
Hans



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
> I don't like this syntax, it is awkward and making the code less readable.
>
> 1) You are replacing a normal switch, which may be limited in its abilities but is well known even to beginners with something that has a rather unintuitive syntax. The shift operators are associated to streaming in C++ these days, but you use them differently here. Someone who reads this code who is not familiar with eswitch will not immediately understand this. Why did you chose operator>> instead of operator<< ? I think the choice is arbitrary and therefore hard to remember.
>
> 2) Your syntax requires one to type a lot of characters. I don't think one should replace the switch but if one did, the following syntax would be more economic and easier to remember, because it is less arbitrary
>
> eswitch( value, case(match1), lambda1, case(match2), lambda2 , … , default(), lambdaN );

PS: I forgot to replace `case` by `case_` and `default` by `default_` but you get the idea.


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
On 2019-11-12 13:32, Hans Dembinski via Boost wrote:
>> I don't like this syntax, it is awkward and making the code less readable.
>>
>> 1) You are replacing a normal switch, which may be limited in its abilities but is well known even to beginners with something that has a rather unintuitive syntax. The shift operators are associated to streaming in C++ these days, but you use them differently here. Someone who reads this code who is not familiar with eswitch will not immediately understand this. Why did you chose operator>> instead of operator<< ? I think the choice is arbitrary and therefore hard to remember.
>>
>> 2) Your syntax requires one to type a lot of characters. I don't think one should replace the switch but if one did, the following syntax would be more economic and easier to remember, because it is less arbitrary
>>
>> eswitch( value, case(match1), lambda1, case(match2), lambda2 , … , default(), lambdaN );
>
> PS: I forgot to replace `case` by `case_` and `default` by `default_` but you get the idea.

On the topic of better syntax, there are a few examples in Boost:

https://www.boost.org/doc/libs/1_71_0/libs/phoenix/doc/html/phoenix/modules/statement/switch__statement.html
https://www.boost.org/doc/libs/1_71_0/doc/html/lambda/le_in_details.html#lambda.switch_statement

Though, I'm not convinced about the usefulness of the proposed eswitch
library.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [Boost][Proposal] library for enhanced switch syntax.

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
> Why did you chose operator>> instead of operator<< ?
Because my intention was to show "control flow transition" which goes in my
case from left to right, thus ">>" and not the other way around "<<".

eswitch( line ) >>  // pass control to following "case_"
case_( ... ) >> // pass control to lambda and execute if case_ was matched
[]{...} >> // pass control to "falling_option"
fallthrough_ >> ...;

> // I think the choice is arbitrary and therefore hard to remember.
Nope, it was intentionally. Also I had on my mind following syntax with
pipes "|":

eswitch( line ) |
case_( "^.+ 200 .+$"_r, []{...} ) |
case_( "^.+: .+$"_r,    []{...} ) |
default_( []{...} );

> I don't think one should replace the switch...
This sentence confuses me. What do you mean?
You're either saying that we shouldn't try to extend "switch" anyhow or you
meant something else.
In case of( "switch shouldn't be extended..." ), then please explain your
position in more details? Otherwise it sounds like: "I just don't like it".
What I see everywhere, people actually extend "switch", for instance:
"Swift", "C#", "Java", "JavaScript", "LLVM StringSwitch" and I think there
is even more.
I think there is a reason for that, because "switch" is much convenient and
more readable then "if-elseif-else" in some cases.

By the way syntax isn't a problem, I can change it.

Regards
RAbdumalikov

вт, 12 нояб. 2019 г. в 12:32, Hans Dembinski <[hidden email]>:

> > I don't like this syntax, it is awkward and making the code less
> readable.
> >
> > 1) You are replacing a normal switch, which may be limited in its
> abilities but is well known even to beginners with something that has a
> rather unintuitive syntax. The shift operators are associated to streaming
> in C++ these days, but you use them differently here. Someone who reads
> this code who is not familiar with eswitch will not immediately understand
> this. Why did you chose operator>> instead of operator<< ? I think the
> choice is arbitrary and therefore hard to remember.
> >
> > 2) Your syntax requires one to type a lot of characters. I don't think
> one should replace the switch but if one did, the following syntax would be
> more economic and easier to remember, because it is less arbitrary
> >
> > eswitch( value, case(match1), lambda1, case(match2), lambda2 , … ,
> default(), lambdaN );
>
> PS: I forgot to replace `case` by `case_` and `default` by `default_` but
> you get the idea.
>
>

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost