330 likes | 581 Views
ConceptClang : An Implementation of C++ Concepts in Clang. Larisse Voufo , Marcin Zalewski , and Andrew Lumsdaine Open Systems Lab, Indiana University. Designing Concepts in C++. Concepts are the basis of generic programming C++ does not have concepts language feature
E N D
ConceptClang: An Implementation of C++ Concepts in Clang Larisse Voufo, MarcinZalewski, and Andrew Lumsdaine Open Systems Lab, Indiana University
Designing Concepts in C++ • Concepts are the basis of generic programming • C++ does not have concepts language feature • Generic programming uses templates • Concepts were proposed but not accepted for C++11 • Insufficient implementation experience • ConceptGCC was the only prototypeavailable
ConceptClang Goals: • An Infrastructure for Implementing Concepts: • In Clang • Extensible and easily accessible • Independent from any “Concepts” proposal. • “Texas”, “Indiana”, Other? • Adaptable to any proposal. • An implementation based on pre-Frankfurt standard draft.
Clang: • What: • LLVM Front-end for the C family of Languages • Why: • Carefully designed coding guidelines. • Modern C++ implementation technology • Highly structured code • Easily understandable • Modular—Library-based approach • License allows extension and experimentation
Templates: Example • Template Definition: • Template Use: • traverse a range and accumulate its elements • Need: an iterator, a binary operation template<typenameInputIterator, typenameT, typenameBinaryFunction> Taccumulate(InputIterator first, InputIteratorlast, Tinit, BinaryFunctionbin_op) { for (; first != last; ++first) init= bin_op(init, *first); return init; } vector<int> v; inti = accumulate(v.begin(), v.end(), 0, plus<int>());
Templates: Mechanism Template Definition: Template Use: Specialization: Instantiation: template<typenameInputIterator, typenameT, typenameBinaryFunction> Taccumulate(…) { … } int accumulate(vector<int>::iterator first, vector<int>::iterator last, intinit, plus<int> bin_op); Type-Check Once! vector<int> v; inti= accumulate<vector<int>::iterator, int, plus<int> > (v.begin(), v.end(), 0, plus<int>()); int accumulate (vector<int>::iterator first, vector<int>::iterator last, intinit, plus<int> bin_op) { … }
Concepts in C++: Explicit Support • Constrained Templates: • Concept Definitions: • Concept Models template<typenameI, typenameT, typenameBinOp> requires (InputIterator<I>, BinaryFunction<BinOp>) Taccumulate(Ifirst, Ilast, Tinit, BinOpbin_op) { for (; first != last; ++first) init= bin_op(init, *first); return init; } concept InputIterator<typename T>{ typenamevalue_type; T operator++(T); } concept BinaryFunction<class BinOp>{ … } concept_mapInputIterator<vector<int>::iterator> { typedefintvalue_type; T operator++(T t) { … } } concept_mapBinaryFunction<plus<int> >{ … } Modeling Mechanisms may Differ… Notion Of Models Prevails.
Constrained Templates: Mechanism Constrained Template Definition: Constrained Template Use: Specialization: Instantiation: template<typenameI, typenameT, typenameBinOp> requires(InputIterator<I>, BinaryFunction<BinOp>) Taccumulate(…) { … } int accumulate(vector<int>::iterator first, vector<int>::iterator last, intinit, plus<int> bin_op); Type-check + Constraint-check Once! vector<int> v; inti= accumulate<vector<int>::iterator, int, plus<int> > (v.begin(), v.end(), 0, plus<int>()); int accumulate (vector<int>::iterator first, vector<int>::iterator last, intinit, plus<int> bin_op) { … }
Templates:From Unconstrained to Constrained • Poor error detection and diagnosis: • Point to internals of library • Lengthy, hard-to-understand • WORSE: Semantic errors are not detected • Language “tricks”: • too complex, error-prone, and limited • NEED: Separate type-checking! • Errors detected at source • Diagnoses indicate exact source • Without leaking implementation details • Clang pretty-prints • Separate type-checking • We know who to blame!
Templates: Problem – Example 1 Templates: Solution – Example 1 • Template Use: • Compiler error: vector<void*> v; inti = accumulate(v.begin(), v.end(), 0, plus<int>()); Larisse-Voufos-MacBook-Pro:Experimentsannlarysm$ g++ accumulate.cpp -o accumulate /usr/include/c++/4.2.1/bits/stl_numeric.h: In function ‘_Tpstd::accumulate(_InputIterator, _InputIterator, _Tp, _BinaryOperation) [with _InputIterator = __gnu_cxx::__normal_iterator<void**, std::vector<void*, std::allocator<void*> > >, _Tp = int, _BinaryOperation = std::plus<int>]’: accumulate.cpp:23: instantiated from here /usr/include/c++/4.2.1/bits/stl_numeric.h:115: error: invalid conversion from ‘void*’ to ‘int’ /usr/include/c++/4.2.1/bits/stl_numeric.h:115: error: initializing argument 2 of ‘_Tpstd::plus<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = int]’ Larisse-Voufos-MacBook-Pro:Experimentsannlarysm$ ~/llvm.test/llvm/Debug+Asserts/bin/clang++ accumulate.cpp -o accumulate accumulate.cpp:40:10: error: no matching function for call to 'accumulate' inti = accumulate(v.begin(), v.end(), 0, plus<int>()); ^~~~~~~~~~ accumulate.cpp:21:3: note: candidate template ignored: constraints check failure [with I = __gnu_cxx::__normal_iterator<void **, std::vector<void *, std::allocator<void *> > >, T = int, BinOp = std::plus<int>] T accumulate(I first, I last, T init, BinOpbin_op) { ^ accumulate.cpp:20:24: note: Concept map requirement not met. requires (InputIterator<I>, BinaryFunction<BinOp>) ^ accumulate.cpp:20:1: note: Constraints Check Failed: accumulate. requires (InputIterator<I>, BinaryFunction<BinOp>) ^ 1 error generated. Incompatible Binary Operator!
Templates: Solution – Example 2 Templates: Problem – Example 2 • Template Use: • Compiler error: vector<int> v; sort(v.begin(), v.end(), not_equal_to<int>()); Larisse-Voufos-MacBook-Pro:Experimentsannlarysm$ ~/llvm.test/llvm/Debug+Asserts/bin/clang++ accumulate.cpp -o accumulate accumulate.cpp:44:2: error: no matching function for call to 'sort' sort(v.begin(), v.end(), not_equal_to<int>()); ^~~~ accumulate.cpp:34:6: note: candidate template ignored: constraints check failure [with I = __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >, BinOp = std::not_equal_to<int>] void sort(I first, I last, BinOp comp) { ^ accumulate.cpp:33:31: note: Concept map requirement not met. requires (RandomAccessIterator<I>, StrictWeakOrdering<BinOp>) ^ accumulate.cpp:33:1: note: Constraints Check Failed: sort. requires (RandomAccessIterator<I>, StrictWeakOrdering<BinOp>) ^ 1 error generated. (None !?) Not Valid Ordering!
Concepts (in C++): Essential Elements • Concept Definitions • Concept refinements • Associated declarations • Concept Modeling • Concept models • Implementations • Generic Algorithm Definition: • Constrained templates • Constrained environments • Generic Algorithm Use: • Type-checking, extended • Constraint-check Gathers models for constraints • Models for constraints • Stored with specialization
Implementation Considerations: General • Concept Definitions • Scoping checks • Lookup in refinements and associated requirements • Concept Modeling • Scoping checks • Check: model vs. concept • Lookup in concept • Generic Algorithm Definition: • Check: constraints validity • Check: body vs. constraints • Lookup in constraints • Generic Algorithm Use: • Constraint-check • Gather models for constraints • Store models for constraints • with Specialization – How?
Implementation Considerations: Across Different Proposals • Concept Definitions • Non-dependence checks • Lookup in refinements and associated requirements • Concept Modeling • Non-dependence checks • Check: model vs. concept • Lookup in concept • Generic Algorithm Definition: • Check: constraints validity • Check: body vs. constraints • Lookup in constraints • Generic Algorithm Use: • Constraint-check • Gather models for constraints • Store models for constraints • With specialization – How? • Instantiation Stronger vs. Weaker Constraints? Pseudo-signatures vs. Valid Expressions? Infrastructure Layer: No Difference! Implicit vs. Explicit Modeling? How and Where?
ConceptClang Implementation • Concept Definitions • All Declarations in ConceptDecl class • Name lookup, modified. • Concept Modeling • All Declarations in ConceptMapDecl class • Check: model vs. concept • Concept map generation procedure • Name lookup, modified • Generic Algorithm Definition: • Check: constraints validity • Concept map archetypes: represent constraints • Check: body vs. constraints • Name Lookup, modified • Generic Algorithm Use: • Constraint-check procedure • Returns models for constraints • Store models for constraints • In structure for specialization. • Instantiation • Rebuild declaration references
ConceptClang Implementation • Concept Definitions • All Declarations in ConceptDecl class • Name Lookup, modified. • Concept Modeling • All Declarations in ConceptMapDecl class • Check: model vs. concept • Concept map generation procedure • Name Lookup, modified • Generic Algorithm Definition: • Check: constraints validity • Concept map archetypes: represent constraints • Check: body vs. constraints • Name Lookup, modified • Generic Algorithm Use: • Constraint-check procedure • Returns models for constraints • Store models for constraints • In structure for specialization. • Instantiation • Rebuild declaration references
ConceptClang Implementation:Modified Lookup • Scope flags: control lookup • e.g. DeclScope parsing a context with multiple declarations • New scope flags: • ConceptDefnScope • ConceptMapScope • RestrictedScope • Restricted- InstantiationScope
ConceptClang Implementation • Concept Definitions • All Declarations in ConceptDecl class • Name Lookup, modified. • Concept Modeling • All Declarations in ConceptMapDecl class • Check: model vs. concept • Concept map generation procedure • Name Lookup, modified • Generic Algorithm Definition: • Check: constraints validity • Concept map archetypes: represent constraints • Check: body vs. constraints • Name Lookup, modified • Generic Algorithm Use: • Constraint-check procedure • Returns models for constraints • Store models for constraints • In structure for specialization. • Instantiation • Rebuild declaration references Mutual Recursion
Constraints Check Procedure Constrained Template Definition: Constrained Template Use: Specialization: Maps for Constraints: • Found or generated template<typenameI, typenameT, typenameBinOp> requires(InputIterator<I>, BinaryFunction<BinOp>) Taccumulate(…) { … } int accumulate(vector<int>::iterator first, vector<int>::iterator last, intinit, plus<int> bin_op); Type-Check Constraints-Check vector<int> v; inti= accumulate<vector<int>::iterator, int, plus<int> > (…); InputIterator<vector<int>:: iterator>, BinaryFunction<plus<int> >
Concept Map Generation:Satisfying Concept Refinements Concept Definition: Parsed Model Definition: Final Model Implementation: Refinement maps: concept ForwardIterator <typenameI> : InputIterator<I>, OutputIterator<I>{ … } concept_map ForwardIterator <vector<int>::iterator>{ … } Type-Check Constraints-Check concept_mapForwardIterator <vector<int>::iterator>{ … } InputIterator <vector<int>::iterator>, OutputIterator <vector<int>::iterator>
Concept Map Template Generation:Satisfying Concept Refinements Concept Definition: Parsed Model Definition: Final Model Implementation: Refinement maps: concept ForwardIterator <typenameI> : InputIterator<I>, OutputIterator<I>{ … } concept_map ForwardIterator <vector<int>::iterator>{ … } Type-Check Constraints-Check template<typenameIter> requires (InputIterator<Iter>, OutputIterator<Iter>) concept_mapForwardIterator<Iter>{ … } InputIterator<Iter>, OutputIterator<Iter>
ConceptClang Implementation:References to Associated Declarations • Concept Definitions • All Declarations in ConceptDecl class • Name Lookup, modified. • Concept Modeling • All Declarations in ConceptMapDecl class • Check: model vs. concept • Concept map generation procedure • Name Lookup, modified • Generic Algorithm Definition: • Check: constraints validity • Concept map archetypes: represent constraints • Check: body vs. constraints • Name Lookup, modified • Generic Algorithm Use: • Constraint-check procedure • Returns models for constraints • Store models for constraints • In structure for specialization. • Instantiation • Rebuild declaration references
ConceptClang Implementation:References to Associated Declarations Template Definition: PARSING Template Specialization: INSTANTIATION template<typename T,…> requires(C<T,…>,…) void func(T a,…) { … foo(…); … } void func(int a,…); void func(int a,…) { … foo(…); … } concept_mapC<T,…> { … foo(…); … } … concept_mapC<int,…> { … foo(…); … } …
ConceptClang Implementation:References to Constrained Templates • Similar to concept map templates generation • Constraints of calling context == template constraints • Parsing + Rebuilding call expression.
ConceptClang Implementation:References to Constrained Templates Template Definitions: Temporary Template Specialization: PARSING Template Specializations: INSTANTIATION template<typename T,…> requires(C<T,…>,…) void oth_func(T a,…); void oth_func(int a,…); void func(int a,…); template<typename T,…> requires(CD<T,…>,…) void func(T a,…) { … oth_func(a,…); … } void func(int a,…) { … oth_func(a,…); … } concept_mapC<int,…>; … void oth_func(T a,…); concept_mapCD<int,…>; … concept_mapC<T,…>; …
ConceptClang Implementation • Reusability and automation • Clang implementation is reused: • Type substitution • Type deduction • Parsing mechanism • Scoping • Unique identification • Concept Definitions • All Declarations in ConceptDecl class • Name Lookup, modified. • Concept Modeling • All Declarations in ConceptMapDecl class • Check: model vs. concept • Concept map generation procedure • Name Lookup, modified • Generic Algorithm Definition: • Check: constraints validity • Concept map archetypes: represent constraints • Check: body vs. constraints • Name Lookup, modified • Generic Algorithm Use: • Constraint-check procedure • Returns models for constraints • Store models for constraints • In structure for specialization. • Instantiation • Rebuild declaration references
Essential Data Structures Scope: DeclScope | ConceptDeclScope | RestrictedScope ConceptDecl Concept Parameters TemplateDecl Template Parameters DeclContext FoldingSetNode ConceptMapDecl Template Parameters ≠ 0, for concept map templates Scope: DeclScope | ConceptMapScope | RestrictedScope Decl … NamedDecl Name
ConceptClang Implementation • Concept Definitions • All Declarations in ConceptDecl class • Name Lookup, modified. • Concept Modeling • All Declarations in ConceptMapDecl class • Check: model vs. concept • Concept map generation procedure • Name Lookup, modified • Generic Algorithm Definition: • Check: constraints validity • Concept map archetypes: represent constraints • Check: body vs. constraints • Name Lookup, modified • Generic Algorithm Use: • Constraint-check procedure • Returns models for constraints • Store models for constraints • In structure for specialization. • Instantiation • Rebuild declaration references
Concept-based overloading //#1 template <class FI> FI min_element(FI first, FI last); //#2 template <class T> T* min_element(T* first, T* last); //Instantiation chooses #2 int *p1, *p2; int* p = min_element(p1, p2); //#1 template <class FI> FI min_element(FI first, FI last); //#2 template <class FI> requires ForwardIterator<FI> FI min_element(FI first, FI last); //#3 template <class RI> requires RandomAccessIterator<RI> RI min_element(RI first, RI last); concept_mapForwardIterator<int*>; concept_mapRandomAccessIterator<int*>; //Instantiation chooses #3 int *p1, *p2; int* p = min_element(p1, p2); • Function Overloading: • Partial order on functions • Select most specialized function • Concept-based Overloading: • Constraints resolve ambiguities • Select most constrained as well • Question: Given functions A and B, when: • A is more constrained than B, and • B is more specialized than A • Select which one? //#B template <class T> T* min_element(T* first, T* last); //#A template <class FI> requires ForwardIterator<FI> FI min_element(FI first, FI last); concept_mapForwardIterator<int*>; //Instantiation chooses ??? int *p1, *p2; int* p = min_element(p1, p2);
Concept-based overloading • Question: Given functions A and B, when: • A is more constrained than B, and • B is more specialized than A • Select which one? • Answer: • Pre-Frankfurt C++: B • ConceptClang: A • Right answer? Open question! //#B template <class T> T* min_element(T* first, T* last); //#A template <class FI> requires ForwardIterator<FI> FI min_element(FI first, FI last); concept_mapForwardIterator<int*>; //Instantiation chooses ??? int *p1, *p2; int* p = min_element(p1, p2);
Practical Example: Mini-BGL template<typename G, typename C, typenameVis, typenameQType> requires (VertexListGraph<G>, IncidenceGraph<G>, ReadWriteMap<C>, SameType<ReadMap<C>::key, Graph<G>::vertex>, Color<ReadMap<C>::value>, Visitor<Vis, G>, Bag<Qtype>) voidgraph_search(const G& g, vertex s, Vis vis, C c, Qtype& Q); template<typename G, typename C, typename Vis> requires (VertexListGraph<G>, IncidenceGraph<G>, ReadWriteMap<C>, SameType<ReadMap<C>::key, Graph<G>::vertex>, Color<ReadMap<C>::value>, BFSVisitor<Vis, G>) voidbreadth_first_search(const G& g, vertex s, C c, Vis vis) { pair<vertex_iter, vertex_iter> iter_pair = vertices(g); for(vertex_iteriter = iter_pair.first, iter_end= iter_pair.second; iter != iter_end; ++iter) { vertex u = *iter; initialize_vertex(vis, u, g); set(c, u, white()); } std::queue<int> Q; graph_search(g, s, vis, c, Q); }
Thank You! Questions? http://www.generic-programming.org/software/ConceptClang/ template <typename G, typename C, typename Vis> requires (VertexListGraph<G>, IncidenceGraph<G>, ReadWriteMap<C>, SameType<ReadMap<C>::key, Graph<G>::vertex>, Color<ReadMap<C>::value>, BFSVisitor<Vis, G>) voidbreadth_first_search(const G& g, vertex s, C c, Vis vis) { pair<vertex_iter, vertex_iter> iter_pair = vertices(g); for(vertex_iteriter = iter_pair.first, iter_end= iter_pair.second; iter != iter_end; ++iter) { vertex u = *iter; initialize_vertex(vis, u, g); set(c, u, white()); } std::queue<int> Q; graph_search(g, s, vis, c, Q); }