Named Requirements for C++0X Concepts

Similar documents
Toward a Proposal for Object Templates in C++0x

A Proposal to Improve const_iterator Use from C++0X Containers

Axioms: Semantics Aspects of C++ Concepts

Deducing the type of variable from its initializer expression (revision 3)

Simplifying C++0x Concepts

Progress toward Opaque Typedefs for C++0X

Deducing the type of variable from its initializer expression (revision 4)

Deducing the type of variable from its initializer expression Programming Language C++ Document no: N1721=

A Proposal to Add Random-Number Distributions to C++0x

common_type and duration

Proposed Wording for Concepts (Revision 7)

Working Draft, Extensions to C++ for Modules

Structured bindings with polymorphic lambas

Technical Specification: Concepts

Expansion statements. Version history. Introduction. Basic usage

Wording for lambdas in unevaluated contexts

The PCAT Programming Language Reference Manual

Proposed Wording for Variadic Templates (Revision 1)

Operator Dot Wording

Implicit Evaluation of auto Variables and Arguments

Modules: ADL & Internal Linkage

Concepts for the C++0x Standard Library: Iterators

Record of Response: National Body Comments ISO/IEC PDTS Technical Specification: C++ Extensions for Concepts

Modules:Context-Sensitive Keyword

Operator Dot Wording

The Syntax of auto Declarations

American National Standards Institute Reply to: Josee Lajoie

Concepts for C++0x. 1 Overview 2. 2 Review of generic programming and its terminology 3

Static If Considered

Implicit Evaluation of auto Variables and Arguments

Concepts for CDT. Supervisor Prof. Peter Sommerlad. Author Lukas Wegmann. Technical Adviser Thomas Corbat

Proposed Wording for Variadic Templates

Extended friend Declarations

More STL algorithms (revision 2)

Avoiding undefined behavior in contracts

Working Draft, Extensions to C++ for Modules

Proposing Standard Library Support for the C++ Detection Idiom, v2

Iterator Concepts for the C++0x Standard Library

Appendix. Grammar. A.1 Introduction. A.2 Keywords. There is no worse danger for a teacher than to teach words instead of things.

Concepts (Revision 1)

For Loop Exit Strategies (Revision 3)

Working Draft, C++ Extensions for Concepts

C++ Module TS Issues List Gabriel Dos Reis Microsoft

I m sure you have been annoyed at least once by having to type out types like this:

Short Notes of CS201

Botet C++ generic overload functions P0051

CS201 - Introduction to Programming Glossary By

New wording for C++0x Lambdas

JML and Java 1.5+ David R. Cok Eastman Kodak Company, Research Laboratories 9 October 2008 SAVCBS08 workshop

Lesson 12 - Operator Overloading Customising Operators

Abstract This paper proposes the ability to declare multiple variables initialized from a tuple or struct, along the lines of:

C++14 and Concepts. Bjarne Stroustrup. Texas A&M University

Review of the C Programming Language

The SPL Programming Language Reference Manual

1 Lexical Considerations

Working Draft, C++ Extensions for Concepts

Integrating Concepts: Open items for consideration

The New C Standard (Excerpted material)

Working Draft, C++ extensions for Concepts

Language Extensions for Vector loop level parallelism

Review of the C Programming Language for Principles of Operating Systems

\n is used in a string to indicate the newline character. An expression produces data. The simplest expression

The C++ Standards Committee: Progress & Plans

Proposal of Bit field Default Member Initializers

Abstract This paper proposes the ability to declare multiple variables initialized from a tuple or struct, along the lines of:

An Incomplete Language Feature

On the Coroutines TS

p0616r0 - de-pessimize legacy <numeric> algorithms with std::move

Merging Modules Contents

More Natural Arithmetic in C++

Adding attribute reflection to C++.

Generalized pointer casts

Introduction to C++ Introduction. Structure of a C++ Program. Structure of a C++ Program. C++ widely-used general-purpose programming language

Typescript on LLVM Language Reference Manual

IMPLEMENTING THE LINQ QUERY LANGUAGE INTO THE C++ PROGRAMMING LANGUAGE USING A PREPROCESSOR

P0591r4 Utility functions to implement uses-allocator construction

Extending static_assert

Introduction to C++ with content from

RAQUEL s Relational Operators

DEMO A Language for Practice Implementation Comp 506, Spring 2018

Chapter 1 Summary. Chapter 2 Summary. end of a string, in which case the string can span multiple lines.

Fast Expression Templates

ucalc Patterns Examine the following example which can be pasted into the interpreter (paste the entire block at the same time):

Assignment 1: grid. Due November 20, 11:59 PM Introduction

Technical aspects of VTL to SQL translation Prepared by Regional Statistical Office in Olsztyn, Poland

MATVEC: MATRIX-VECTOR COMPUTATION LANGUAGE REFERENCE MANUAL. John C. Murphy jcm2105 Programming Languages and Translators Professor Stephen Edwards

p0407r2 - Allocator-aware basic_stringbuf

Override Control Using Contextual Keywords

Forward declaration of enumerations

4. An interpreter is a program that

Motivation was to facilitate development of systems software, especially OS development.

The following is an excerpt from Scott Meyers new book, Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs.

CS /534 Compiler Construction University of Massachusetts Lowell. NOTHING: A Language for Practice Implementation

Concepts are Adjectives, not Nouns

Compiler construction

Ch. 10: Name Control

Software Development with C++ Templates

Concepts for the C++0x Standard Library: Introduction

Absolute C++ Walter Savitch

Allowing Class Template Specializations in Associated Namespaces (revision 1)

Transcription:

Named Requirements for C++0X Concepts Document #: WG21/N2581 = J16/08-0091 Date: 2008-03-13 Revises: None Project: Programming Language C++ Reference: ISO/IEC IS 14882:2003(E) Reply to: Walter E. Brown <wb@fnal.gov> Chris Jefferson <chris@bubblescope.net> Alisdair Meredith <alisdair.meredith@codegear.com> James Widman <widman@gimpel.com> Contents 1 Introduction 1 2 Example 1: basic utility of named requirements 1 3 Example 2: named requirements within concept definitions 2 4 Example 3: refinement clauses as named requirements 3 5 Design decisions 4 6 Proposed wording 4 7 Summary and conclusion 6 8 Acknowledgments 7 As the term is used in mainstream cognitive science and philosophy of mind, a concept is an abstract idea or a mental symbol, typically associated with a corresponding representation in a language or symbology. WIKIPEDIA, 2008-03-03 1 Introduction This paper proposes to augment C++0X with a small new feature, named requirements, in order to achieve considerable reduction in the bulk, the complexity, and the redundancy now needed in the specification of non-trivial constrained templates. Motivated by the experiences of the LWG in specifying the constraints on the well-known algorithms of the Standard Library, rephrasing the requirements via the proposed feature leads to improved ease of specification and comprehension consistent with classical code factorization techniques. 2 Example 1: basic utility of named requirements LWG has observed that concepts with several interrelated requirements today often require duplication of non-trivial requirements in multiple contexts. As a representative example, consider 1

2 N2581: Named Requirements for C++0X Concepts the requirements of the constrained template std::inner_product. The template s declaration (reformatted for clarity) was originally articulated as shown in Listing 1: 1 // Listing 1 2 template<inputiterator Iter1, InputIterator Iter2, typename T> 3 requires Multiplicable< Iter1::reference 4, Iter2::reference 5 > 6 && Addable< T 7, Multiplicable< Iter1::reference 8, Iter2::reference 9 >::result_type 10 > 11 && Assignable< T 12, Addable< T 13, Multiplicable< Iter1::reference 14, Iter2::reference 15 >::result_type 16 >::result_type 17 > 18 T 19 inner_product( Iter1 first1, Iter1 last1, Iter2 first2, T init ); Note that the non-trivial Multiplicable<> requirement is replicated in its entirety within the Addable<> requirement, and that the Addable<> requirement is itself replicated in its entirety within the Assignable<> requirement. Thus Multiplicable<> appears three times in all (as highlighted in red), and Addable<> appears twice (as highlighted in brown). Each replication arises in the context of an ever-larger surrounding requirement. However, employing the proposed named requirements, the redundancy and bulk of these requirements can be greatly reduced by the simple technique of naming the requirements and thereafter referring to previously-named requirements instead of replicating them. The resulting code, shown in Listing 2, is vastly simpler to read and comprehend: 1 // Listing 2 2 template<inputiterator Iter1, InputIterator Iter2, typename T> 3 requires mult = Multiplicable<Iter1::reference, Iter2:reference> 4 && add = Addable<T, mult::result_type> 5 && Assignable<T, add::result_type> 6 T 7 inner_product( Iter1 first1, Iter1 last1, Iter2 first2, T init ); Note that we do not propose to require that each requirement be named. It is up to the user to determine whether a name should be attached to any given requirement. 3 Example 2: named requirements within concept definitions The code in Listing 3 is adapted from Peter Gottschling s technical report Fundamental Algebraic Concepts in Concept-Enabled C++ 1 : 1 TR 638, Indiana University, October 2006.

N2581: Named Requirements for C++0X Concepts 3 1 // Listing 3 2 auto concept BinaryIsoFunction< typename Op, typename Elem > { 3 requires std::callable<op, Elem, Elem>; 4 requires std::convertible< std::callable<op, Elem, Elem>::result_type 5, Elem 6 >; 7 typename result_type = std::callable<op, Elem, Elem>::result_type; 8 }; Note in particular the three occurrences (highlighted in red) of the identical Callable<> requirement in the above code. This redundancy could be addressed via named requirements as shown in Listing 4: 1 // Listing 4 2 auto concept BinaryIsoFunction< typename Op, typename Elem > { 3 requires call = std::callable< Op, Elem, Elem >; 4 requires std::convertible< call::result_type, Elem >; 5 typename result_type = call::result_type; 6 }; 4 Example 3: refinement clauses as named requirements Refinement clauses in concept definitions provide another source of potential redundancy. Often a concept refining a non-trivial concept will several times want to refer to the refined concept. For example consider Listing 5 below, in which Complicated<> may denote an arbitrarily lengthy concept being refined. 1 // Listing 5 2 concept Refining< typename T, typename U > : Complicated<T,U> { 3 requires std::hasplus< Complicated<T,U>::result_type >; 4 }; Note the similarity to the already discussed problem of repeating a complex requirement, as demonstrated in Listing 6. 1 // Listing 6 2 concept Refining< typename T, typename U > { 3 requires c = Complicated<T,U>; 4 requires std::hasplus< c::result_type >; 5 }; It seems desirable to permit the analogous specification in the context of a refinement clause. Therefore, to simplify the specification as well as for consistency, we propose to allow named requirements in refinement clauses as well as in the body of concepts. The notation, demonstrated in Listing 7, follows naturally from the previous examples. 1 // Listing 7 2 concept Refining< typename T, typename U > : c = Complicated<T,U> { 3 requires std::hasplus< c::result_type >; 4 };

4 N2581: Named Requirements for C++0X Concepts 5 Design decisions 5.1 Scope As shown in the above examples, the minimum useful scope for a requirement s name is from the point of its declaration to the end of the clause introduced by requires. As further illustrated by the previous examples, we propose that a requirement s name be additionally injected into the scope of the concept or constrained template in which it arises. Further, a name thus injected into a concept should be visible to any refining concept, and a name thus injected into a constrained class template should be visible to any derived template. 5.2 Syntax In order to name a requirement, we propose the declarative syntax: name = requirement. We considered the additional use of a keyword (e.g., alias or using), but believe this feature needs no additional keyword. Most requirements already follow the requires keyword or (in the case of multiple requirements) follow a subsequent &&; we believe this is sufficient context to parse the declaration of a requirement s name. We do not propose this feature for use in connection with requirements expressed in the short form. However, in the interests of completeness (not to mention simplifying the grammar), we do propose to allow a named requirement wherever N2571 proposes to allow a requirement to be written. If adopted, we ll be able to write a = C<T>: 1. as a refinement-specifier (14.9.3 [concept.refine] p1), and 2. as a requirement (14.10.1 [temp.req] p1), thus permitting a named requirement to be declared within: a) a member-requirement (9.2 [class.mem]) b) an associated-requirement (14.9.1.3 [concept.req]) c) the optional requires-clause of an axiom-definition (14.9.1.4 [concept.axiom]), and d) the optional requires-clause of a constrained template declaration (14.10). Finally, as we have no realistic use case for a named requirement pack expansion, we propose that any such construct be ill-formed: 1 // Listing 8 2 template<typename... Ts> 3 requires a = C<Ts>... // error: requirement aliases may refer only 4 // to requirements that are not pack expansions 5 void 6 f( Ts... ); 6 Proposed wording This section s proposed wording is with respect to N2571, and may therefore need minor adjustment should that paper be revised (e.g., so as to cause renumbering). This proposal is purely an extension to N2571; except for very small additions to the underlying grammar, it requires no changes to any existing wording. The proposed wording is presented in two parts. The Minimal wording provides for the definition and use of alias names, the most basic form of the proposed named requirements feature. The Recommended additional wording provides for the name injection of these alias names, supplementing their presence in the scope of template/concept parameters as provided under Minimal wording) and allowing these names to be used in derived classes and refining concepts.

N2581: Named Requirements for C++0X Concepts 5 6.1 Minimal wording In 14.9.3 [concept.refine], augment the grammar definition of requirement-specifier; in 14.10.1 [temp.req], augment the grammar definition of requirement and add a grammar definition of req-alias-def. Text to be added is indicated in red: refinement-specifier : requirement : req-alias-def : req-alias-def opt :: opt nested-name-specifier opt concept-id req-alias-def opt :: opt nested-name-specifier opt concept-id! :: opt nested-name-specifier opt concept-id identifier = Append the following after 14.10.1 [temp.req] p5 ( A negative requirement requires... ): A req-alias-def introduces the identifier as a name in the scope of: the concept parameters, when the req-alias-def appears in a refinement-specifier (14.9.3); the member declaration, when the req-alias-def appears in a member-requirement (9.2); the enclosing concept, when the req-alias-def appears in an associated-requirement (14.9.1.3); the axiom, when the req-alias-def appears in the optional requires-clause of an axiomdefinition (14.9.1.4); or the template parameters declared in the template-parameter-list immediately before the requires keyword, when the req-alias-def appears in the optional requires-clause of a constrained template declaration. The name is an alias for the concept instance named in the requirement. It is inserted into its scope immediately when the req-alias-def is seen. [ Example: 1 #include <concepts> 3 concept C<typename T> { 4 typename R; 5 } 7 template<typename T> 8 requires J = C<T> 9 J::R // qualified lookup finds type name R 10 // within the concept map archetype C<T > (3.4.3.3) 11 f( T ); 13 auto concept BinaryFunction<typename Op, typename Elem> { 14 requires call = std::callable<op, Elem, Elem>; 15 requires std::convertible<call::result_type, Elem>; 16 typename result_type = call::result_type; 17 }; end example ] If a req-alias-def appears in a requirement that is the pattern of a pack expansion, the program is ill-formed. [ Example:

6 N2581: Named Requirements for C++0X Concepts 1 concept C<typename... Ts> {} 3 template<typename... Ts> 4 requires a = C<Ts>... // error: requirement aliases may refer only 5 // to requirements that are not pack expansions 6 void 7 f( Ts... ); end example ] 6.2 Recommended additional wording Continue the above text, appending the following: When a req-alias-def appears in a refinement-specifier (14.9.3), the alias name is also inserted into the scope of the concept; this is known as an injected-requirement-name. When a req-alias-def appears in the optional requires-clause in the definition of a constrained class template or member class of a class template or any further-nested class, the alias name is also inserted into the scope of the class or class template being defined as an injected-requirementname. For purposes of access checking, the injected-requirement-name is treated as if it were a public member name. [ Example: 1 #include <concepts> 3 concept B<typename T, typename U> { 4 typename result_type; 5... 6 }; 8 concept C<typename T, typename U> : b = B<T,U> { 9 requires std::hasplus<b::result_type>; 10 typename result_type; 11... 12 }; 14 template<typename T> 15 requires c = C<T,T> 16 c::b::result_type 17 f( const T& ); end example ] Also append the following after 3.3.1 [basic.scope.pdecl] p7 ( The point of declaration for an injected-class-name... ): The point of declaration for an injected-requirement-name (14.10.1) is immediately following the opening brace of the definition of the concept or class. 7 Summary and conclusion In this paper, we have proposed a named requirements feature as a small extension to the syntax of concept requirements and refinements, and have demonstrated that the proposed feature

N2581: Named Requirements for C++0X Concepts 7 provides significant benefits in the form of decreased redundancy in the specifications of concepts and constrained templates, with concomitant improvements in the clarity and comprehensibility of the resulting code. We respectfully urge that the proposal and its underlying issues be considered on a time scale consistent with C++0X. However, we recommend that CWG consider this paper only after it has duly approved the basic concepts proposal. 8 Acknowledgments We thank Bjarne Stroustrup and Douglas Gregor, principal instigators of the concepts work, for their efforts in promulgating what promises to become one of the major features of C++0X. We also thank the Fermi National Accelerator Laboratory s Computing Division, sponsor of Fermilab s participation in the C++ standards effort, for its past and continuing support of efforts to improve C++ for all our user communities.