Curiously Recursive Template Problems with Aspect Oriented Programming

Curiously Recursive Template Problems with Aspect Oriented Programming

By Hugo Arregui, Carlos Castro, Daniel Gutson

Overload, 20(109):20-23, June 2012


Hugo Arregui, Carlos Castro and Daniel Gutson work out how to combine two useful techniques.

Aspect Oriented Programming (AOP) is a programming paradigm that makes possible to clearly express programs separated into ‘aspects’, including appropriate isolation, composition and reuse of the aspect code [ Kiczales97 ]. AOP defines weaving as the process of composing the aspects into a single entity.

Independently, there are situations in which a base class needs to know its subclass, e.g. for type-safe downcasts. The Curiously Recurring Template Pattern (CRTP) is a C++ idiom in which a class X derives from a class template instantiation using X itself as template argument [ Abrahams04 ]. This way, the base class can know the derived type.

Both AOP and the CRTP are widely adopted C++ programming techniques. In particular, there exists an AOP easy implementation using templates [ Spinczyk05 ]. However, a C++ grammar incompatibility arises when combining AOP and CRTP. While there exists a C++ dialect called AspectC++ [ Spinczyk05 ], we don’t evaluate in this work its ability to combine AOP and CRTP since it requires its own compiler extensions and so its not standard C++. Here we look at a simple solution implemented in standard C++ that addresses the issue without any overhead penalty.

Problems combining AOP + CRTP

There are some situations where combining the benefits of AOP and CRTP are desirable; however, as we will show below, some problems arise when applying together the individual standard procedures of each technique.

The code in Listing 1 shows an attempt of adding functionality, through aspects, to a base class named Number .

//basic class
class Number
{
  protected:
  UnderlyingType n;
};

//aspects
template <class NextAspect>
struct ArithmeticAspect: public NextAspect
{
  FULLTYPE operator+
    (const FULLTYPE& other) const;
    // What type is FULLTYPE?
  FULLTYPE operator- 
    (const FULLTYPE& other) const;
  FULLTYPE& operator+= 
    (const FULLTYPE& other);
  FULLTYPE& operator-= 
    (const FULLTYPE& other);
};

template <class NextAspect>
struct LogicalAspect : public NextAspect
{
  bool operator! () const;
  bool operator&& (const FULLTYPE& other) const;
  bool operator|| (const FULLTYPE& other) const;
};

//decorating Number with aspectual code
typedef LogicalAspect
  <ArithmeticAspect<Number > > MyIntegralType;
			
Listing 1

We can observe that the return type of ArithmeticAspect’s operator + and - needs to know the ‘complete type’ ( FULLTYPE ) when trying to extend the base class functionality through operator overloading. We will address this issue in the following sections.

A minimal solution

The basic principle of this solution does not differ in essence from the traditional solution mentioned before.

Problem

Number takes the place of the last aspect in the aspects list. However, Number itself needs to know (as a template template argument) the aspects list, to which it itself belongs, leading to a ‘chicken or egg’ grammatical dilemma.

For example, if Number knew the complete type, it could use it as a return type for its operators as shown in Listing 2.

template <template <class> class Aspects>
class Number
{
  typedef Aspects<Number<Aspects>> FullType;
...
};
ArithmeticAspect<Number<ArithmeticAspect>>
			
Listing 2

This shows the weaving of a single aspect with CRTP, which works perfectly:

  LogicalAspect<ArithmeticAspect<Number<??>>>

On the other hand, this exposes the problem when trying to weave one additional aspect, since it requires a template template argument, which the aspects lists can’t grammatically fulfill as coded above.

We present two solutions: the first being the simplest using C++11’s template alias [ Reis ], and the second using variadic templates (templates that take a variable number of arguments, recently introduced in C++11 [ Gregor ]) as the only C++11’s feature, which in turn, can also be easily implemented in C++98 as well. Both use a common language idiom introduced next, which aims to be used as a library providing a friendly syntax and reduced reusable code.

The proposed language idiom

A possible solution would be to apply some handcrafted per-case base template aliases, as shown below:

  //with template alias:
  template <class T>
  using LogicalArithmeticAspect =
     LogicalAspect<ArithmeticAspect<T>>;

  //without template alias:
  template <class T>
  struct LogicalArithmeticAspect
  {
    typedef 
       LogicalAspect<ArithmeticAspect<T>> Type;
  };

and with minor changes in the Number
 base class’s code, we could write the following declaration:
  LogicalArithmeticAspect
  <
    Number<LogicalArithmeticAspect>
  >

Although this does the trick it tends to be impractical, and also would increment linearly the number of related lines of code in terms of the amount of combinations to be used, which would cause a copy-paste code bloat.

However, we will look for a more generic way to address this issue, avoiding drone code cloning, and being able to encapsulate the method into a library.

Therefore, in order to provide a user-oriented and easy to use library, we'll use C++11’s new variadic-templates so we can cleanly express our intention: to ‘decorate’ the base class with a list of aspects. An example of what we intend to achieve is shown below:

  Decorate<Number>::with<ArithmeticAspect,
                         LogicalAspect>

The skeleton of the Decorate class is shown in Listing 3, the details of which will vary in the solutions below.

template
  <template <template <class> class> class Base>
class Decorate
{
  public:
    template<template <class> class ... Aspects>
    struct with
    {
      //...
    };

    //...

  private:
    struct Apply 
    { … 
    };
};
			
Listing 3

In both solutions, the with nested class and the Apply internal helper will have different implementations.

Solution 1: Using C++11’s template alias

In this solution, the Decorate::with implementation is as shown in Listing 4, and the internal helper Apply structure also uses templates aliases (see Listing 5).

template<template <class> class ... Aspects>
struct with
{
  template <class T>
  using AspectsCombination = 
     typename Apply<Aspects...>::template Type<T>;
  typedef
    AspectsCombination
      <Base<AspectsCombination>> Type;
};
			
Listing 4
template<template <class> class A1,
         template <class> class ... Aspects>
struct Apply<A1, Aspects...>
{
  template <class T>
  using Type = A1
    <typename Apply
       <Aspects...>::template Type<T>>;
};
			
Listing 5

Despite the implementation between the two solutions differing, the purpose is the same and the underlying idea is explained next in the second solution.

Solution 2: Not using C++11’s template alias

In this solution, the Decorate::with implementation is as shown in Listing 6.

template<template <class> class ... Aspects>
struct with
{
  typedef typename Apply<Aspects...>::Type TypeP;
  typedef typename TypeP::template Binding
  <
    Base<TypeP::template Binding>
  >::Type Type;
};
			
Listing 6

Combining aspects

Now that we have a list of aspects, how could we combine them? The solution we propose is to create a Binder class, as shown in Listing 7.

struct None 
{
};
template <template <class> class A,
   class B = None>
struct Binder
{
  template <class T>
  struct Binding
  {
    typedef
      typename Binder<A>::template Binding
      <
        typename B::template
         Binding<T>::Type
      >::Type Type;
   };
};
template<template <class> class T>
struct Binder<T, None>
{
  template <class P>
  struct Binding
  {
    typedef T<P> Type;
  };
};
			
Listing 7

Binder encapsulates an aspect (as a template template argument) within a complete type Binder<Aspect> . Additionally, it enables us to do a ‘ bind ’ operation to the next aspect or base class, by accessing to the Binding inner class.

The way in which Binder finally allows us to construct the whole type is shown below.

  Binder<ArithmeticAspect,
  Binder<LogicalAspect>>::Binding<Number>::Type

Let’s analyze step-by-step this listing (from the innermost to the outermost definition):

  1. Binder<LogicalAspect> uses the second definition, it just provides a complete type for the aspect with a possibility to bind to another complete type
  2. Binder<ArithmeticAspect, Binder<LogicalAspect>> uses the first definition.

    The binding generates a Binder to the ArithmeticAspect , and binds it to Binder<LogicalAspect>::Binding<T> generating a template template argument combining both aspects. (In short, Binder generates a template template argument – combining Arithmetic with Logical aspects – to be used in the base class).

  3. Finally, the type is injected into the base Number class.

Since such an implementation is not immediately obvious, we have provided a simplified version in Listing 8 for illustration.

template <template <class> class A,
   class B = None>
struct Binder
{
  template <class T>
  struct Binding
  {
    typedef 
       Binder<A>::Binding
       <
         B::Binding<T>::Type
       >::Type Type;
   };
};
			
Listing 8

Now we’ve got a Binder that implements the weaving of aspects and finally inject them into the base class.

Applying the list of Aspects to the Number class

The only remaining detail is to apply our Bind class to the list of aspects. To do this, we define a helper structure called Apply , that recursively applies the Binder class to each aspect, as shown in Listing 9.

template <template <class> class ... Aspects>
struct Apply;
  template <template <class> class T>
  struct Apply<T>
  {
    typedef Binder<T> Type;
  };
  
  template<template <class> class A1,
    template <class> class ... Aspects>
  struct Apply<A1, Aspects...>
  {
    typedef Binder<A1, typename Apply
    <
      Aspects...
    >::Type> Type;
  };

  template<template <class> class ... Aspects>
  struct with
  {
    typedef
      typename Apply<Aspects...>::Type TypeP;
    typedef
      typename TypeP::template Binding
      <
        Base<TypeP::template Binding>
      >::Type
    Type;
  };
			
Listing 9

We use the Apply helper struct to generate a resulting aspect as the weaving of all the given aspects, and inject it to the base class.

Then ::Type contains the type we needed, and that’s it!

Using the library

The library that implements this idiom provides two tools: the means to obtain the FullType , and the means to build it.

Listing 10 shows a way of obtaining the FullType with an Aspect .

//basic class
template 
   <template <class> class Aspects>
   class Number
{
  typedef Aspects<Number<Aspects>> FullType;
  //...
};

// aspect example
template <class NextAspect>
struct ArithmeticAspect: public NextAspect
{
  typedef typename NextAspect::FullType FullType;
  FullType
     operator+ (const FullType& other) const;
  // ...
};
			
Listing 10

Let’s see a final example, using two of the aspects mentioned before:

  typedef Decorate<Number>::with<ArithmeticAspect,
            LogicalAspect>::Type
			ArithmeticLogicalNumber;

Please note that both solutions presented before expose the same interface so this snippet is equally applicable to them.

C++98 alternative and complete code

The same idea can be implemented using typelists in previous C++ standards, such as C++98.

The complete code of the library and examples both for C++11 and C++98 can be accessed in http://cpp-aop.googlecode.com

Final comments

We think that the solution to the problem exposed in this article could become straightforward by enhancing the language with a reserved keyword to get the full type. We suggest to consider this problem for the next revision of the language standard.

References

[Abrahams04] Abrahams, David; Gurtovoy, Aleksey. 2004. C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond . Addison-Wesley. ISBN 0-321-22725-5.

[Gregor] Gregor, Douglas; Järvi, Jaako; Powell, Gary. Variadic Templates (Revision 3). [N2080=06-0150]. Programming Language C++. Evolution Working Group.

[Kiczales97] Kiczales, Gregor; John Lamping, Anurag Mendhekar, Chris Maeda, Cristina Lopes, Jean-Marc Loingtier, and John Irwin (1997). ‘Aspect-Oriented Programming’. Proceedings of the European Conference on Object-Oriented Programming , vol.1241. pp. 220–242.

[Reis] Dos Reis, Gabriel; Stroustrup, Bjarne. Template Aliases (Revision 3). [N2258=07-0118]. Programming Language C++. Evolution Working Group.

[Spinczyk05] Spinczyk, Olaf; Lohmann, Daniel; Urban, Matthias. ‘AspectC++: an AOP Extension for C++’. Software Developer’s Journal , pages 68-76, 05/2005.






Your Privacy

By clicking "Accept Non-Essential Cookies" you agree ACCU can store non-essential cookies on your device and disclose information in accordance with our Privacy Policy and Cookie Policy.

Current Setting: Non-Essential Cookies REJECTED


By clicking "Include Third Party Content" you agree ACCU can forward your IP address to third-party sites (such as YouTube) to enhance the information presented on this site, and that third-party sites may store cookies on your device.

Current Setting: Third Party Content EXCLUDED



Settings can be changed at any time from the Cookie Policy page.