Proposal: statement expansion

300 views
Skip to first unread message

sshi...@hotmail.com

unread,
Jun 24, 2014, 10:54:07 AM6/24/14
to std-pr...@isocpp.org

It would be nice to have a statement expansion in C++17.

Here is an example of a switch generation based on the list of "case" classes,
which defines mapping integer values to types.

template <class T>
void ImpFunc();

template <int Val_,class T>
struct Case
 {
  const int Val = Val_ ;

  using Type = T ;
 };

template <class ... CC>
void SwitchFunc(int key)
 {
  switch( key )
    {
     { case CC::Val : ImpFunc<typename CC::Type>(); break; }...
    }
 }

....

int key;

....

SwitchFunc< Case<1,T1> , Case<2,T2> , Case<3,T3> >(key);

In the given example the statement, enclosed in the brackets { }... is expanded according the given template
parameter list.

Maurice Bos

unread,
Jun 24, 2014, 2:20:44 PM6/24/14
to std-pr...@isocpp.org
How about declarations?

(For example, template<typename...Base> struct Thing : Base... { using
Base::foo;... }; to have 'using Base::foo;' for every Base.)
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposal...@isocpp.org.
> To post to this group, send email to std-pr...@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.

Ville Voutilainen

unread,
Jun 24, 2014, 2:22:50 PM6/24/14
to std-pr...@isocpp.org
On 24 June 2014 21:20, Maurice Bos <m-o...@m-ou.se> wrote:
> How about declarations?
>
> (For example, template<typename...Base> struct Thing : Base... { using
> Base::foo;... }; to have 'using Base::foo;' for every Base.)

This one is old news, http://cplusplus.github.io/EWG/ewg-active.html#102
is supported by EWG and will proceed further.

There's currently no accepted proposal/idea for statement expansions, but
there is ongoing for for expression expansions.

Maurice Bos

unread,
Jun 24, 2014, 4:57:02 PM6/24/14
to std-pr...@isocpp.org
If i remember correctly, the support was for "using Pack...;" (by
allowing "using A, B, C;"), not for "using Pack;..." (which would mean
"using A; using B; using C;", and would work for other declarations
too).

David Krauss

unread,
Jun 26, 2014, 11:00:33 PM6/26/14
to std-pr...@isocpp.org

On 2014–06–25, at 2:22 AM, Ville Voutilainen <ville.vo...@gmail.com> wrote:

There's currently no accepted proposal/idea for statement expansions, but
there is ongoing for for expression expansions.

Where? A quick scan of EWG issues and paper titles only turns up using-declaration and pack accessor extensions.

I recall discussion of expression expansions on this list, but it didn’t go anywhere as nobody could make a strong case for a particular meaning — it’s half a solution, in search of a problem.

The one meaning which would be clear is the comma operator, but that’s better covered by the semicolon as in this proposal.

To the OP and anyone else in favor: Please exclude labeled-statements from pattern compound-statements.

{ case N: blah(); } ... // OK (N is a pack).
case N: { blah(); } ... // Error: unexpanded pack, ellipsis expands nothing.
case some_constant: { blah(); } ... // Error: repeated label.

This will perhaps result from natural grammatical specification, but the distinction deserves mention in the proposal. The case with no unexpanded pack in the label should be diagnosed at parse time, not only when the expansion produces an ill-formed duplicate label.

Also, I thought I’d posted this earlier, but I don’t see it now: Please don’t include declarations in this proposal, because the semantics are unclear. Adding a crazy element to a clear and obvious proposal will only sink the good part.

The requirement of braces, or a compound-expression, nicely prevents pack-generated declarations from leaking into the enclosing scope. I prefer this to simply forbidding declaration-statements. For example, you wouldn’t want the ellipsis to transform a declaration into an expression by the ambiguity rule.

sshi...@hotmail.com

unread,
Jun 28, 2014, 1:29:55 AM6/28/14
to std-pr...@isocpp.org


On Friday, June 27, 2014 7:00:33 AM UTC+4, David Krauss wrote:

To the OP and anyone else in favor: Please exclude labeled-statements from pattern compound-statements.

{ case N: blah(); } ... // OK (N is a pack).
case N: { blah(); } ... // Error: unexpanded pack, ellipsis expands nothing.
case some_constant: { blah(); } ... // Error: repeated label.

This will perhaps result from natural grammatical specification, but the distinction deserves mention in the proposal. The case with no unexpanded pack in the label should be diagnosed at parse time, not only when the expansion produces an ill-formed duplicate label.

Also, I thought I’d posted this earlier, but I don’t see it now: Please don’t include declarations in this proposal, because the semantics are unclear. Adding a crazy element to a clear and obvious proposal will only sink the good part.

The requirement of braces, or a compound-expression, nicely prevents pack-generated declarations from leaking into the enclosing scope. I prefer this to simply forbidding declaration-statements. For example, you wouldn’t want the ellipsis to transform a declaration into an expression by the ambiguity rule.

 
Good points.

 

David Krauss

unread,
Jun 28, 2014, 11:29:36 AM6/28/14
to std-pr...@isocpp.org
On 2014–06–28, at 1:29 PM, sshi...@hotmail.com wrote:

On Friday, June 27, 2014 7:00:33 AM UTC+4, David Krauss wrote:

case some_constant: { blah(); } ... // Error: repeated label.
 
Good points.

Whoops, that line is missing a pack, if you’re going to recycle this example it should be 

case some_constant: { N; } ...

Larry Evans

unread,
Sep 7, 2016, 5:24:24 AM9/7/16
to std-pr...@isocpp.org
On 06/26/2014 10:00 PM, David Krauss wrote:
[snip]

> Please don’t include declarations in this proposal,
> because the semantics are unclear. Adding a crazy element
> to a clear and obvious proposal will only sink the good
> part.

> The requirement of braces, or a compound-expression, nicely
> prevents pack-generated declarations from leaking into the
> enclosing scope. I prefer this to simply forbidding
> declaration-statements. For example, you wouldn’t want the
> ellipsis to transform a declaration into an expression by
> the ambiguity rule.
>
[snip]

David, could you provide an example where declaration
expansion semantics are unclear. I curious because there is
one use case where declaration expansion into the enclosing
scope would be useful. The BOOST_SPIRIT_DEFINE_ and
BOOST_SPIRIT_DEFINE macros here:

https://github.com/boostorg/spirit/blob/x3-devel/include/boost/spirit/home/x3/nonterminal/rule.hpp#L159

"expand" several overloaded parse_rule
declaration/definitions into the enclosing scope. The
BOOST_SPIRIT_DEFINE macro use is shown here:

https://github.com/boostorg/spirit/blob/x3-devel/example/x3/calc4c/grammar.cpp#L36

which expands into:

template<typename Iterator, typename Context>
inline bool parse_rule
( x3::rule<class expression, ast::program> rule_
, ...){...}
template<typename Iterator, typename Context>
inline bool parse_rule
( x3::rule<class term, ast::program> rule_
, ...){...}
template<typename Iterator, typename Context>
inline bool parse_rule
( x3::rule<class factor, ast::operand> rule_
, ...){...}

(For those curious about the reasons why overloaded
parse_rule functions are needed, the vastly simplified
code here:

https://gist.github.com/cppljevans/3d3bec54be8f3d0c4d8b94af84a6e529

and in particular, the comments around BOOST_SPIRIT_DEFINE_
on line 198 should, hopefully, make the reasons clear.
)

Now, in order to replace the BOOST_SPIRIT_DEFINE* macros
with some new "statement expansion" syntax, I guess
something like the following (where namespace keyword is
"re-used" with a new context dependent meaning) would work:

template<typename... T>
namespace my_stmt_exp(T... arg)
{
stmt_to_exp[T|arg]...
}

where stmt_to_exp[T|arg] means some statements, including
possibly declarations, with occurrences of T and|or args.
This would inject the stmt_to_exp[T|arg]... into the current
scope.

With something like this, the BOOST_SPIRIT_DEFINE macro
definition could be replaced with:

template<typename... RuleDef>
namespace boost_spirit_define(RuleDef... def)
{
template <typename Iterator, typename Context, typename Attribute>

inline bool parse_rule(

decltype(def)::lhs_type rule_

, Iterator& first, Iterator const& last

, Context const& context, Attribute& attr)

{

using boost::spirit::x3::unused;

auto const& def_ = (def);

return def_.parse(first, last, context, unused, attr);

}... //expand parse_rule overloads into enclosing scope.
}

which would allow replacement of the BOOST_SPIRIT_DEFINE
macro use here:

https://github.com/boostorg/spirit/blob/x3-devel/example/x3/calc4c/grammar.cpp#L36

with:

boost_spirit_define(
expression =
term
>> *( (char_('+') >> term)
| (char_('-') >> term)
)
,

term =
factor
>> *( (char_('*') >> factor)
| (char_('/') >> factor)
)
,

factor =
uint_
| '(' >> expression >> ')'
| (char_('-') >> factor)
| (char_('+') >> factor)
);

Are there any problems with that?

-regards,
Larry


Reply all
Reply to author
Forward
0 new messages