280 likes | 432 Vues
Towards a General Template Introspection Library in C++. István Z ólyomi , Zolt án Porkoláb Department of Programming Languages and Compilers Eötvös Loránd University, Budapest, Hungar y {scamel, gsd}@elte.hu. C++ Templates. Provides language support for parametric polymorphism
E N D
Towards a General Template Introspection Library in C++ István Zólyomi, Zoltán Porkoláb Department of Programming Languages and Compilers Eötvös Loránd University, Budapest, Hungary {scamel, gsd}@elte.hu
C++ Templates • Provides language support for parametric polymorphism • “Type-aware smart macros” • Many checks are delayed until instantiation • No restrictions on parameters • Templates alone form a Turing-complete functional language inside C++ • Based on template specializations
Issues on Templates • Lazy evaluation: instantiate template members only on request • Wider scale of parameters supported • Avoid code bloat • Unexpected late errors • Hard to decode error messages • Classic example: • Member function of a class template using srot() instead of sort() compiles • Compile error when calling member function
Introspection • Entity can observe its own state • Information gained in runtime from: • Interpreter (Perl, Ruby, etc) • VM (Java, .Net, etc) • Environment (C++ RTTI) • Information gained from compiler • Direct language support • Hand written exploits
Introspection in C++ • Limited direct support in the language • sizeof • Would be useful to • Make restrictions on template parameters (concept checking) • Extend current type system (generate conversions, operations) • Optimization (e.g. expression templates)
Compile-time Adaptation • A program can observe its state • May make decisions depending on state • Data structures • Implementation strategies • Template metaprogramming, e.g. boost::mpl • E.g. a container decide to store: • Comparable values in binary tree • Other values in list • Compiler rules apply for generated program
Concept Checking • Concept: list of requirements on a type • Enforce concepts on template parameters immediately at instantiation • Improve implementation quality • Especially useful at the STL, e.g. for iterator categories
Concept Checking in Other Languages • Parameter type must implement interface or derive from base class • Java interface Sortable { ... } class SortedList <T extends Sortable> ... • Eiffel class SORTED_LIST [T -> COMPARABLE] ... • Similar in functional languages
Concept Checking in Other Languages • Ada: generic interface, no inheritance required generic --- Element type type T is private; --- Comparision on element type with function “<“ (X,Y: T) return boolean is <>; package Sorted_List ... end --- Generics are instantiated explicitly package SL is new Sorted_List(MyType, “<=“);
Concept Checking Techniques • Currently used in C++: • require (GNU STL) • boost::concept_check • Shortages • No elementary conditions identified • No orthogonality • No composition: • “Fulfill or die” philosophy • Implicit conjunction • No cooperation with other libraries
Ideal Concept Checking Library • Compile time “execution” • Identifying elementary conditions • Orthogonal design • Boolean results instead of aborting compilation • Condition composition • Cooperation with metaprogramming libraries • Something like an extension to boost::type_traitsfor concept checking
Goals • Implement introspection library to enable concept checking that is close to ideal • Cooperation with metaprogramming libraries (e.g. boost::mpl) • Use only standard C++ • No language extension • No typeof operator • No compiler-specific features • No external tools (e.g. gcc-xml)
Programming Techniques • Ellipse: accept any parameter void f(...); • Function overload Yes isOk(ExpectedType); // expected case No isOk(...); // rescue case • Return types have different sizes struct No { char dummy; }; struct Yes { char dummy[2]; };
Programming Techniques • Map return types to boolean values sizeof( isOk(expression) ) == sizeof(Yes); • Convenience macro for mapping // --- The same with macro shortcut bool res = CONFORMS( isOk(expression) );
Programming Techniques • boost::enable_if // --- Enabled case template <bool b, class T> struct enable_if { typedef T Result; }; // --- Specialized disabled case template <class T> struct enable_if<false> {};
Programming Techniques • SFINAE rule(Substitution failure is not an error) // --- Expected case for T enable_if<sizeof(T::Feature), Yes> f(T&); // --- Rescue case No f(...); bool res = CONFORMS( f(Type()) );
Elementary Conditions • Checks implemented for • Existence of embedded type with name • Existence of class member with name • Exact type of embedded type • Exact type of member (both function and data)
Embedded Type Name • Inspect if type has an embedded type with given name • Need macros PREPARE_TYPE_CHECKER(iterator); ... // --- Look for name ‘iterator’ in T const bool res = CONFORMS( TYPE_IN_CLASS(iterator, T) );
Member Name • Inspect if type has a non-type member (either data or function) with given name • Similar to previous condition PREPARE_MEMBER_CHECKER(size); ... // --- Look for member ‘size’ in T const bool res = CONFORMS( MEMBER_IN_CLASS(size, T) );
Nested Type • Inspect nested type if name exists • Cooperate with other tools, e.g. boost::type_traits // --- Inspect traits of nested type const bool isScalar = type_traits<T::value_type>::is_scalar; // --- Inspect exact type const bool isInteger = SameTypes<int, T::value_type>::Result;
Members • Exact type of member if name exists // --- Inspect if ‘size’ is data member const bool isDataMember = CONFORMS( Member<unsigned int>::NonStatic( &T::size ) ); // --- Inspect if ‘size’ is member function typedef unsigned int Fun() const; const bool isMemberFunction = CONFORMS( Member<Fun>::NonStatic( &T::size ) );
Composite Conditions • User can easily assemble complex conditions template <class T> struct LessThanComparable { enum { Conforms = CONFORMS( Function<bool (const T&, const T&)>:: Static( &::operator< ) || CONFORMS( Function<bool (const T&) const>:: NonStatic( &T::operator< ) }; };
Hacking? • Two opinions: • Should be language extension • Should be user code • Language change • Major issue • Must have proved design • Should be based on previous experiences
Open Questions • What is the minimal orthogonal set of conditions? • What other conditions are expected to be implemented? • What conditions are theoretically impossible to implement with current language standard? • DefaultConstructable?
Summary • Separation of introspection from intercession • Implemented elementary conditions • Observation provides compile time bool • Easy to define new user conditions • Arbitrary combination of conditions is possible • And, or, negate • Specialization on this result is possible • Supports compile-time adaptation • Supports concept checking
Further Plans • Implement more elementary conditions • Check theorethical limitation of implementation • Implement a concept-checking library usable in the STL
Thank You! See related material at http://gsd.web.elte.hu