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