conceptclang : an implementation of c++ concepts in clang
DESCRIPTION
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 - PowerPoint PPT PresentationTRANSCRIPT
ConceptClang: An Implementation of C++ Concepts in Clang
Larisse Voufo, Marcin Zalewski, and Andrew LumsdaineOpen 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 prototype available
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<typename InputIterator, typename T, typename BinaryFunction>T accumulate(InputIterator first, InputIterator last, T init, BinaryFunction bin_op) { for (; first != last; ++first) init = bin_op(init, *first); return init;}
vector<int> v;int i = accumulate(v.begin(), v.end(), 0, plus<int>());
Templates: MechanismTemplate Definition:
Template Use:
Specialization:
Instantiation:
template<typename InputIterator, typename T, typename BinaryFunction>T accumulate(…) { …}
vector<int> v;int i = accumulate<vector<int>::iterator, int, plus<int> >(v.begin(), v.end(), 0, plus<int>());
int accumulate(vector<int>::iterator first, vector<int>::iterator last, int init, plus<int> bin_op);
int accumulate(vector<int>::iterator first, vector<int>::iterator last, int init, plus<int> bin_op) { …}
Type-CheckOnce!
Concepts in C++: Explicit Support Constrained Templates:
Concept Definitions: Concept Models
template<typename I, typename T, typename BinOp>requires (InputIterator<I>, BinaryFunction<BinOp>)
T accumulate(I first, I last, T init, BinOp bin_op) { for (; first != last; ++first) init = bin_op(init, *first); return init;}
concept InputIterator<typename T>{ typename value_type; T operator++(T);}
concept BinaryFunction<class BinOp>{…
}
concept_map InputIterator<vector<int>::iterator> { typedef int value_type; T operator++(T t) { … }}concept_map BinaryFunction<plus<int> >{
… }
Modeling Mechanisms may Differ…
Notion Of Models Prevails.
Constrained Template Definition:
Constrained Template Use:
vector<int> v;int i = accumulate<vector<int>::iterator, int, plus<int> >(v.begin(), v.end(), 0, plus<int>());
Constrained Templates: MechanismSpecialization:
Instantiation:
template<typename I, typename T, typename BinOp>requires(InputIterator<I>, BinaryFunction<BinOp>)T accumulate(…) { …}
int accumulate(vector<int>::iterator first, vector<int>::iterator last, int init, plus<int> bin_op);
int accumulate(vector<int>::iterator first, vector<int>::iterator last, int init, plus<int> bin_op) { …}
Type-check+
Constraint-checkOnce!
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 Template Use:
Compiler error:
vector<void*> v;int i = accumulate(v.begin(), v.end(), 0, plus<int>());
Larisse-Voufos-MacBook-Pro:Experiments annlarysm$ g++ accumulate.cpp -o accumulate/usr/include/c++/4.2.1/bits/stl_numeric.h: In function ‘_Tp std::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 ‘_Tp std::plus<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = int]’
Incompatible
Binary Operator!
Larisse-Voufos-MacBook-Pro:Experiments annlarysm$ ~/llvm.test/llvm/Debug+Asserts/bin/clang++ accumulate.cpp -o accumulateaccumulate.cpp:40:10: error: no matching function for call to 'accumulate' int i = 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, BinOp bin_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.
Templates: Solution – Example 1
Templates: Problem – Example 2 Template Use:
Compiler error:
vector<int> v;sort(v.begin(), v.end(), not_equal_to<int>());
(None !?)Not Valid Ordering!
Larisse-Voufos-MacBook-Pro:Experiments annlarysm$ ~/llvm.test/llvm/Debug+Asserts/bin/clang++ accumulate.cpp -o accumulateaccumulate.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.
Templates: Solution – Example 2
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
Pseudo-signatures vs.
Valid Expressions?
Implicit vs. Explicit
Modeling?
Stronger vs. Weaker
Constraints?
How and Where?
Infrastructure Layer: No Difference!
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<typename I, typename T, typename BinOp>requires(InputIterator<I>, BinaryFunction<BinOp>)T accumulate(…) { …}
vector<int> v;int i = accumulate<vector<int>::iterator, int, plus<int> >(…);
int accumulate(vector<int>::iterator first, vector<int>::iterator last, int init, plus<int> bin_op);Constraints-Check
Type-Check
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 <typename I> : InputIterator<I>, OutputIterator<I> { …}
concept_map ForwardIterator <vector<int>::iterator>{ …}
InputIterator<vector<int>::iterator>,OutputIterator<vector<int>::iterator>
Constraints-CheckType-Check
concept_map ForwardIterator<vector<int>::iterator>{ …}
Concept Map Template Generation:Satisfying Concept Refinements
Concept Definition:
Parsed Model Definition:
Final Model Implementation:
Refinement maps:
concept ForwardIterator <typename I> : InputIterator<I>, OutputIterator<I> { …}
template<typename Iter>requires (InputIterator<Iter>, OutputIterator<Iter>) concept_map ForwardIterator<Iter>{ …}
InputIterator<Iter>,OutputIterator<Iter>
Constraints-Check
Type-Check
concept_map ForwardIterator<vector<int>::iterator>{ …}
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
Template Definition:
PARSING
ConceptClang Implementation:References to Associated Declarations
template<typename T,…>requires(C<T,…>,…)void func(T a,…) { … foo(…); …}
Template Specialization:
INSTANTIATION
void func(int a,…);
concept_map C<T,…> { … foo(…); …}
…
concept_map C<int,…> { … foo(…); …}
…
void func(int a,…) { … foo(…); …}
ConceptClang Implementation:References to Constrained Templates Similar to concept map templates generation
Constraints of calling context == template constraints Parsing + Rebuilding call expression.
Template Definitions:
Temporary Template Specialization:
PARSING
ConceptClang Implementation:References to Constrained Templates
template<typename T,…>requires(CD<T,…>,…)void func(T a,…) { … oth_func(a,…); …}
Template Specializations:
INSTANTIATION
void func(int a,…);
void func(int a,…) { … oth_func(a,…); …}
template<typename T,…>requires(C<T,…>,…)void oth_func(T a,…);
void oth_func(T a,…);
void oth_func(int a,…);
concept_map C<int,…>; …
concept_map CD<int,…>; …concept_map C<T,…>; …
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
Reusability and automation Clang implementation is
reused: Type substitution Type deduction Parsing mechanism Scoping Unique identification
Essential Data StructuresConceptDecl
Concept Parameters
ConceptMapDeclTemplate Parameters
≠ 0, for concept map templates
TemplateDeclTemplate Parameters
DeclContext FoldingSetNode
Scope:DeclScope |
ConceptDeclScope | RestrictedScope
Scope:DeclScope |
ConceptMapScope | RestrictedScope
NamedDeclName
Decl …
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 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?
//#1template <class FI> FI min_element(FI first, FI last);
//#2template <class T>T* min_element(T* first, T* last);
//Instantiation chooses #2int *p1, *p2;int* p = min_element(p1, p2);
//#1template <class FI> FI min_element(FI first, FI last);
//#2template <class FI>requires ForwardIterator<FI> FI min_element(FI first, FI last);
//#3template <class RI>requires RandomAccessIterator<RI> RI min_element(RI first, RI last);
concept_map ForwardIterator<int*>;concept_map RandomAccessIterator<int*>;
//Instantiation chooses #3int *p1, *p2;int* p = min_element(p1, p2);
//#Btemplate <class T>T* min_element(T* first, T* last);
//#Atemplate <class FI>requires ForwardIterator<FI> FI min_element(FI first, FI last);
concept_map ForwardIterator<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!
//#Btemplate <class T>T* min_element(T* first, T* last);
//#Atemplate <class FI>requires ForwardIterator<FI> FI min_element(FI first, FI last);
concept_map ForwardIterator<int*>;
//Instantiation chooses ???int *p1, *p2;int* p = min_element(p1, p2);
Practical Example: Mini-BGL
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>) void breadth_first_search(const G& g, vertex s, C c, Vis vis) {
pair<vertex_iter, vertex_iter> iter_pair = vertices(g);for(vertex_iter iter = 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);
}
template <typename G, typename C, typename Vis, typename QType>requires (VertexListGraph<G>, IncidenceGraph<G>, ReadWriteMap<C>, SameType<ReadMap<C>::key, Graph<G>::vertex>,
Color<ReadMap<C>::value>, Visitor<Vis, G>, Bag<Qtype>) void graph_search(const G& g, vertex s, Vis vis, C c, Qtype& 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>) void breadth_first_search(const G& g, vertex s, C c, Vis vis) {
pair<vertex_iter, vertex_iter> iter_pair = vertices(g);for(vertex_iter iter = 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);
}