[aspectc-user] Template metaprograms to process function arguments

Mike Mortensen mmo at fc.hp.com
Thu Feb 1 01:47:43 CET 2007

I'm looking at converting some Design-by-contract type of checks for functions
into an aspect or set of aspects.  A simple case of this is checking for NULL
pointers for a given Framework API.  For example, suppose I have some classes to
represent electrical circuit objects, such as:
   bcmCell, bcmNet, and bcmInstance

An application might build it's own functions using these objects and
might pass pointers to the various 'bcm' classes, like this:

  float GetNetCap(bcmNet *net)
  void GetInstInfo(string& info, bcmInstance* i)
  void GetCellInfo(int a, int b, int c, bcmCell* cellPtr, string header)

A very simple contract is to assume that any bcmNet*, bcmInstance*,or bcmCell* is
not NULL, so that we don't have method calls on a NULL pointer.  As you can see,
in this example, the argument that is one of these pointer types could be anywhere
in the argument list.

What I'm trying to do is 'leverage' the code in the article "On Typesafe Aspect
Implementations in C++" by Lohmann and Spinczyk.  The article is very good!  And it
has an aspect that processes an argument list for MS Windows error handling (page 9)
and 'streams' them out so that they can be part of an error message.
I thought I'd start by creating an aspect that just uses stream operators to print out
the arguments, and then (once this is working) I could overload the stream operators
for bcmNet*, bcmInstance*, and so forth to have the NULL checking...

Although I've used templates (such as template classes and functions) and I've created
various types of aspects before, I must confess I'm not an expert at template metaprograms,
so please forgive me if leveraging this code in this way is a bad or wrong idea. :-)

My example 'program' consists of main.cc and api.h, and my aspect is in DBC.ah. The program
compiles and runs w/o aspects.

I use 'whole program analysis' mode on a Linux system with ac++ and g++-3.x, and the
weave completes without any complaints.  However, when I compile the woven code I get

In file included from src.out/main.cc:229:
src.out/DBC.ah:58: error: duplicate nested type `struct ArgChecker::ArgChecker'
src.out/DBC.ah: In static member function `static ArgChecker*
src.out/DBC.ah:49: error: aggregate `ArgChecker::ArgChecker __instance' has
    incomplete type and cannot be defined
src.out/DBC.ah: In static member function `static void
    ArgChecker::stream_params<TJP, N>::process(std::ostream&, TJP*)':
src.out/DBC.ah:63: error: parse error before `;' token
src.out/DBC.ah: In static member function `static void
    ArgChecker::stream_params<TJP, 1>::process(std::ostream&, TJP*)':
src.out/DBC.ah:72: error: parse error before `;' token

The key issue seems to be that the generated (woven) DBC.ah file contains ArgChecker (the aspect)
within itself.  Here's part of the woven DBC.ah file with line numbers shown:

      46 class ArgChecker {
      47 public:
      48   static ArgChecker *aspectof () {
      49     static ArgChecker __instance;
      50     return &__instance;
      51   }
      52   static ArgChecker *aspectOf () {
      53     return aspectof ();
      54   }
      55 private:
      58    class ArgChecker;
      59 template< class TJP, int N >
      60    struct stream_params {  friend class ::ArgChecker;
      62      static void process (ostream& os, TJP* tjp ) {
      63        os << *tjp->arg<TJP::ARGS-N>() << ", ";
      64        stream_params< TJP, N - 1 >::process( os, tjp);
      65      }
      66    };
      67    class ArgChecker;

I'll also attach it as DBC.ah.out.  Has anyone seen a similar problem before?
Is the error in DBC.ah a problem with how the weaver processed the template metaprogram?
Is there an error in my template definitions for this context?

More generally, if another approach was possible in which the aspect processed the arguments
at runtime, that would be fine too.  However, I need to know the type of the argument so that I
ignore arguments with datatype such as int and string and only consider (and check for NULL) the bcmNet*
and other API arguments.  I'm not sure how to do this with arguments.

With the result() JoinPoint call we can use the JoinPoint::Result type to get
the actual type (instead of a void*), but for arguments, the  arg(int) call
returns a void* and I haven't been able to use argtype(int) as an actual type.
It is defined as a AC::Type rather than an actual C++ type I think....

Does anyone have either suggestions on fixing my template code above or some other general approach for
processing the argument list to check arguments that have some specific, user-defined (i.e. not-built in)

-------------- next part --------------
A non-text attachment was scrubbed...
Name: main.cc
Type: text/x-c++src
Size: 1318 bytes
Desc: not available
URL: <http://www.aspectc.org/pipermail/aspectc-user/attachments/20070131/30a49544/attachment.cc>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: api.h
Type: text/x-chdr
Size: 912 bytes
Desc: not available
URL: <http://www.aspectc.org/pipermail/aspectc-user/attachments/20070131/30a49544/attachment.h>
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: DBC.ah.out
URL: <http://www.aspectc.org/pipermail/aspectc-user/attachments/20070131/30a49544/attachment.ksh>

More information about the aspectc-user mailing list