Class Introspection in C++

Download Report

Transcript Class Introspection in C++

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
GPCE'04, Vancouver
1
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
GPCE'04, Vancouver
2
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
GPCE'04, Vancouver
3
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

GPCE'04, Vancouver
4
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)
GPCE'04, Vancouver
5
Compile-time Adaptation


A program can observe its state
May make decisions depending on state




Template metaprogramming, e.g. boost::mpl
E.g. a container decide to store:



Data structures
Implementation strategies
Comparable values in binary tree
Other values in list
Compiler rules apply for generated program
GPCE'04, Vancouver
6
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
GPCE'04, Vancouver
7
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
GPCE'04, Vancouver
8
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, “<=“);
GPCE'04, Vancouver
9
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
GPCE'04, Vancouver
10
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_traits for concept checking
GPCE'04, Vancouver
11
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)



GPCE'04, Vancouver
12
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]; };
GPCE'04, Vancouver
13
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) );
GPCE'04, Vancouver
14
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> {};
GPCE'04, Vancouver
15
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()) );
GPCE'04, Vancouver
16
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)
GPCE'04, Vancouver
17
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)
);
GPCE'04, Vancouver
18
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)
);
GPCE'04, Vancouver
19
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;
GPCE'04, Vancouver
20
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 )
);
GPCE'04, Vancouver
21
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< )
};
};
GPCE'04, Vancouver
22
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
GPCE'04, Vancouver
23
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?
GPCE'04, Vancouver
24
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
GPCE'04, Vancouver
25
Further Plans



Implement more elementary conditions
Check theorethical limitation of
implementation
Implement a concept-checking library
usable in the STL
GPCE'04, Vancouver
26
Thank You!
See related material at
http://gsd.web.elte.hu
GPCE'04, Vancouver
27