Familiar template syntax for generic lambdas Document #: Date: Project: Audience: Reply-to:

1

D0428R0 2016-09-08 Programming Language C++ Evolution Working Group Louis Dionne

Introduction

C++14 added the ability to define generic lambdas, i.e. lambdas where the operator() of the generated closure-type is a template. This addition was initially proposed in [N3418], which included many different features for generic lambdas, including the functionality proposed by this paper. However, N3418 was not accepted as-is and its successor, [N3559], was accepted instead. N3559 settled on the auto-based syntax that we know in C++14 for defining generic lambdas, leaving the usual template syntax out for lack of clear use cases (according to an author of N3559): [](auto x) { /* ... */ } Unfortunately, this syntax makes it difficult to interact with the type of the parameter(s) and lacks flexibility that is sometimes required, as outlined in the Motivation section. Hence, this paper proposes adding the ability to use the familiar template syntax when defining lambda expressions: [](T x) { /* ... */ } [](T* p) { /* ... */ } [](T (&a)[N]) { /* ... */ }

2

Motivation

There are a few key reasons why the current syntax for defining generic lambdas is deemed insufficient by the author. The gist of it is that some things that can be done easily with normal function templates require significant hoop jumping to be done with generic lambdas, or can’t be done at all. The author thinks that lambdas are valuable enough that C++ should support them just as well as normal function templates. The following details such areas where lambdas are lacking in their current form: 1. The limited form of ”pattern matching” on template argument allowed by C++ in function templates is very useful, and it would be equally useful to allow it in lambda expressions. For example, writing a lambda that accepts a std::vector containing elements of any type (but not another container) is not possible with the current syntax for generic lambdas. Instead, one must write a catch-all generic lambda that accepts any type, and then assume that it is of the proper type, or check that it is not through other means: 1

template struct is_std_vector : std::false_type { }; template struct is_std_vector> : std::true_type { }; auto f = [](auto vector) { static_assert(is_std_vector::value, ""); }; In addition to being verbose, calling the lambda with a type that is not a std::vector will result in a hard error inside the body of the lambda, not a template argument deduction failure. This does not play nicely with other parts of the language such as SFINAE-based detection, and it is obviously not as clear as the equivalent function template. Another instance where ”pattern matching” would be useful is to deconstruct the type of arguments that are template specializations. For example, imagine that we want to get the type of elements stored in the vector in the previous example. Right now, we’d have to write this: auto f = [](auto vector) { using T = typename decltype(vector)::value_type; // ... }; This is cumbersome syntax-wise, and it requires the type to provide a nested alias that does just the right thing. This is not a problem for std::vector, but most types don’t provide such aliases (and in many cases it wouldn’t make sense for them to). Hence, right now, types that do not provide nested aliases or accompanying metafunctions can simply not be deconstructed in lambdas. Instead, it would be much simpler and more flexible to write auto f = [](std::vector vector) { // ... }; 2. It is often useful to retrieve the type of the parameter of a generic lambda, e.g. for accessing a static member function or an alias nested inside it. However, retrieving such a type requires using decltype, which includes its reference and cv qualifiers. This can often lead to unexpected results: auto f = [](auto const& x) { using T = decltype(x); T copy = x; T::static_function(); using Iterator = typename T::iterator; };

// Compiles, but wrong semantics! // Does not compile! // Does not compile!

To work around this unfortunate situation, one must introduce some amount of verbosity: auto f = [](auto const& x) { using T = std::decay_t; T copy = x; T::static_function(); 2

using Iterator = typename T::iterator; }; Furthermore, this problem compounds when trying to make a parameter type dependent on a previous parameter type, because aliases can’t be introduced in that context to reduce verbosity: auto advance = [](auto& it, typename std::decay_t::difference_type n) { // ... }; Instead, it would be much nicer and closer to usual templates if we could simply write auto f = [](T const& x) { T copy = x; T::static_function(); using Iterator = typename T::iterator; }; auto advance = [](It& it, typename It::difference_type n) { // ... }; 3. Perfect forwarding in generic lambdas is more verbose than it needs to be, and the syntax for it is different from what’s usually done in normal function templates. While this is technically a direct corollary of the previous point, the author thinks this is sufficiently annoying to be worth mentioning separately. The problem is that since the only way to get an argument’s type in a lambda is to use decltype, we must resort to the following syntax for perfect forwarding: auto f = [](auto&& ...args) { return foo(std::forward(args)...); }; Exactly why this works is explained in a blog post written by Scott Meyers [Meyers], but the very fact that Meyers had to write a blog post about it is telling. Indeed, the interaction between template argument deduction and reference collapsing rules is already sufficiently complicated that many C++ users would benefit from the cognitive load reduction allowed by a single perfect forwarding syntax for both lambdas and normal functions: auto f = [](T&& ...args) { return foo(std::forward(args)...); };

3

Proposed Wording

Change in 5.1.5 [expr.prim.lambda]/1:

3

lambda-expression: lambda-introducer opt lambda-declarator opt compound-statement Change in 5.1.5 [expr.prim.lambda]/6: The closure type for a non-generic lambda-expression has a public inline function call operator (13.5.4) whose parameters and return type are described by the lambdaexpression’s parameter-declaration-clause and trailing-return-type respectively. For a generic lambda, the closure type has a public inline function call operator member template (14.5.2) whose template-parameter-list consists of the specified template-parameter-list, if any, to which is appended one invented type template-parameter for each occurrence of auto in the lambda’s parameter-declaration-clause, in order of appearance. The invented type template-parameter is a parameter pack if the corresponding parameter-declaration declares a function parameter pack (8.3.5). The return type and function parameters of the function call operator template are derived from the lambda-expression’s trailing-return-type and parameter-declaration-clause by replacing each occurrence of auto in the decl-specifier s of the parameter-declaration-clause with the name of the corresponding invented template-parameter. Change in 5.1.5 [expr.prim.lambda]/7: [. . . ] For a generic lambda with no lambda-capture, the closure type has a conversion function template to pointer to function. The conversion function template has the same invented template-parameter-list, and the pointer to function has the same parameter types, as the function call operator template. [. . . ]

4

Implementation experience

This extension to generic lambdas had been implemented in GCC in 2009 as part of an experiment [GCC]. Thus, it seems implementable.

5

Discussion

There were very few controversial decisions to make in the writing of this paper. The only one was whether to allow a lambda to contain both a template-parameter-list and conventional auto-based parameters. When allowing both syntaxes, we must make a choice regarding the position of the invented template parameters relative to the specified template parameters: [](T, auto) // => template [](auto, T) // => template [](auto) // could be either of the above Note that it does make sense to write the third lambda expression, because we can access the function call operator of a lambda explicitly and thus specify a value for T:

4

auto f = [](auto x) { }; f.operator()(...); We decided to allow mixing both syntaxes and decided to append the invented template parameters to the end of the template-parameter-list, because it seems like the simplest choice, it does not limit expressiveness in any way and it is consistent with what’s done in the proposal for concepts [N4553]. In case this choice is deemed the wrong one, this paper can easily be amended to disallow lambdas from using both the familiar template syntax and auto parameters.

6

Acknowledgements

Thanks Tom Honermann, Nicol Bolas and other members of the std-proposal mailing list for providing comments to improve this paper.

7

References

[N4606] Richard Smith, Working Draft, Standard for Programming Language C++ https://github.com/cplusplus/draft/blob/master/papers/n4606.pdf [Meyers] Scott Meyers, C++14 Lambdas and Perfect Forwarding http://scottmeyers.blogspot.com.tr/2013/05/c14-lambdas-and-perfect-forwarding. html [N3418] Faisal Vali, Herb Sutter, Dave Abrahams, Proposal for Generic (Polymorphic) Lambda Expressions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf [N3559] Faisal Vali, Herb Sutter, Dave Abrahams, Proposal for Generic (Polymorphic) Lambda Expressions (Revision 2) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3559.pdf [GCC] Adam Butcher, Latest experimental polymorphic lambda patches http://gcc.gnu.org/ml/gcc/2009-08/msg00174.html [N4553] Andrew Sutton, Working Draft, C++ extensions for Concepts http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4553.pdf

5

Familiar template syntax for generic lambdas -

all. The author thinks that lambdas are valuable enough that C++ should support them just as well as normal function templates. The following details such areas where lambdas are lacking in their current form: 1. The limited form of ”pattern matching” on template argument allowed by C++ in function templates is very useful ...

132KB Sizes 2 Downloads 129 Views

Recommend Documents

Template - Generic -
Dec 1, 2016 - This three-hour awareness session, led by the New Jersey Office of Homeland Security and Preparedness (NJOHSP), provides you with an ...

pdf syntax
There was a problem previewing this document. Retrying... Download. Connect more apps... Try one of the apps below to open or edit this item. pdf syntax. pdf ...

Merkelized Abstract Syntax Trees
2008. [3] P. Todd. Re: Which clients fully support p2sh and/or multisig? https://bitcointalk.org/index.php? topic=255145.msg2757327#msg2757327. Accessed:.

STABILITY CONDITIONS FOR GENERIC K3 ...
It is extremely difficult to obtain any information about the space of stability conditions on a general triangulated category. Even the most basic questions, e.g. ...

Microbase2.0 - A Generic Framework for Computationally Intensive ...
Microbase2.0 - A Generic Framework for Computationally Intensive Bioinformatics Workflows in the Cloud.pdf. Microbase2.0 - A Generic Framework for ...

Generic Load Regulation Framework for Erlang - GitHub
Erlang'10, September 30, 2010, Baltimore, Maryland, USA. Copyright c 2010 ACM ...... rate on a budget dual-core laptop was 500 requests/s. Using parallel.

Misa Familiar Asuncion.pdf
There was a problem previewing this document. Retrying... Download. Connect more apps... Try one of the apps below to open or edit this item. Misa Familiar ...

generic postcard.pdf
Page 1 of 1. a little. Note. a little. Note. a little. Note. a little. Note. Page 1 of 1. generic postcard.pdf. generic postcard.pdf. Open. Extract. Open with. Sign In.

Origins of Syntax?
questions they address, and the techniques used to check the validity of current ... spring up in the future to explore other aspects of the vast research domain of ..... probabilistic information available in the input to the learner/speaker/hearer.

CERTIFICADO DEFICIT DE APOYO FAMILIAR JUNAEB.pdf ...
Page 1 of 1. CERTIFICADO PARA ACREDITAR DÉFICIT RED DE APOYO FAMILIAR. Nombre del postulante. Rut: Fecha de emisión: Apoyo sólo de la madre o ...

MISA FAMILIAR (EPIFANIA).pdf
MISA FAMILIAR (EPIFANIA).pdf. MISA FAMILIAR (EPIFANIA).pdf. Open. Extract. Open with. Sign In. Main menu. Displaying MISA FAMILIAR (EPIFANIA).pdf.

Syntax-Semantics Interface
Oct 14, 2008 - 1 Course information ... Webpage: http://user.uni-frankfurt.de/∼castrovi ... The syntax-semantics interface: what is its role in the overall design of ...

zsh-syntax-highlighting.zsh(1) - GitHub
zsh-syntax-highlighting.zsh - a shell script. SYNOPSIS. Documentation automatically generated with `zshelldoc'. FUNCTIONS. _zsh_highlight. _zsh_highlight_add_highlight. _zsh_highlight_apply_zle_highlight. _zsh_highlight_bind_widgets. _zsh_highlight_b

Comparative Creole Syntax
Certain verbs permit a zero complementizer and, in fact, se does not allow an overt complementizer. (55) Olu se yu /:J kam. 0 say 2s MOD come. 8. 8.1. 8.2. 8.3. 8.4. 8.5. 8.6. 8.7. Complementizers: summary for Krio .... 'His teeth are as plentiful as

FAMILIAR ESTRAGEMENTS: READING FAMILY IN ...
traditional lay practices and the interests of the political and commercial elite for ...... security and protection that a family offers by giving her a position of status ...... returning to his mother, Tryamour parts company from Ardus, but then r

Evolutionary Learning of Syntax Patterns for Genic ...
classroom use is granted without fee provided that copies are not made or distributed for profit or commercial ... GECCO '15, July 11–15, 2015, Madrid, Spain.

Evolutionary Learning of Syntax Patterns for ... - ACM Digital Library
Jul 15, 2015 - ABSTRACT. There is an increasing interest in the development of tech- niques for automatic relation extraction from unstructured text. The biomedical domain, in particular, is a sector that may greatly benefit from those techniques due

Better Learning and Decoding for Syntax Based SMT ...
Data made available by the courtesy of Microsoft .... Part-of-Speech mapping template: whether the ..... clude that PSDIG and Pharaoh each excel on dif-.

Syntax-Semantics Interface
Oct 14, 2008 - tion (in this case of C); the structure that results is an adjunction structure. ... VP. V. NP. Det N'. N. Figure 2: C-Command. Compositionality ...

Syntax-Semantics Interface
Oct 14, 2008 - In Government-and-Binding theory, the name given to the abstract underlying level .... of individuals, taken to constitute the domain of discourse; (b) an .... allows examples like which picture of herself did Mary buy? to be ...

Evolutionary Learning of Syntax Patterns for Genic ...
Evolutionary Learning of Syntax Patterns. Key aspects. 10. ➔ Multi-objective fitness: ◇ f=(Accuracy, FPR, Regex length). ◇ we purposefully avoided to include ...

Generic Desired Adaptation Outcomes
Robust policies, programmes and actions for CC adaptation. 3. Accurate weather forecasting, reliable seasonal predictions, climate projections & effective early.

Enriched syntax-based meaning representation for ... - Semantic Scholar
ABSTRACT. In Question Answering a major challenge is the fact that similar meaning is very often expressed with different surface realizations in questions and in sentences containing the answer. In this paper we propose an enriched syntax-based repr