[aspectc-user] Problem with using arg<i>()

Olaf Spinczyk os at aspectc.org
Mon Aug 25 09:27:07 CEST 2014


Hi Sander!

C++ gives us some limitations here: As arg<I>() is a template, the "I" must be
*constant*. Only if it is constant, the function call can be resolved and the
type of the argument will be determined at compile time. In order to iterate
over  the arguments you have to write a small template metaprogramm. Here is an
excerpt of the AspectC++ test program "StaticTrace", which shows how that can be
done:

---
#ifndef __Trace_ah__
#define __Trace_ah__

#include <iostream>
using namespace std;

template <int I> struct ArgPrinter {
  template <class JP> static inline void work (JP &tjp) {
    ArgPrinter<I - 1>::work (tjp);
    cout << "Arg " << I << ": " << *tjp.template arg<I - 1> () << endl;
  }
};

template <> struct ArgPrinter<0> {
  template <class JP> static inline void work (JP &tjp) {}
};

aspect Trace {
  template <class JP> void print_args (JP &tjp) {
    ArgPrinter<JP::ARGS>::work (tjp);
  }
  advice call("% A::%(...)" || "% no_args()") : before()  {
    tjp->arg(0); // TODO: a workaround, because on demand code generation
                   // does not check the instantiated template
    cout << JoinPoint::filename () << ":" << JoinPoint::line () << endl;
    print_args (*tjp);
  }
};

#endif // __Trace_ah__
---

Please note that the (ugly) workaround mentioned as "TODO..." is still needed. :-(

An alternative implementation uses the non-template variant tjp->arg(i), where
"i" is *not* necessarily constant. However, this function yields a void-pointer.
You would have to implement a big if-construct in order to cast the result to
the correct type at runtime. The argument type is encoded as a string (C++ ABI
name mangling) and can be accessed with tjp->argtype(i). Note that the variant
(above) works for any data type that can be printed on a stream. No changes on
the aspect are needed if you create a new class with an operator <<. It works
automatically. For dynamic variant is not that easily extensible.

Best regards,

Olaf


On 08/23/2014 03:25 PM, Sander Kersten wrote:
> Hi,
>
> I'm completely new to ac++, I'm trying to make a simple tracing aspect as
> practice. I've created the following aspect:
>
> #include <iostream>
>
> aspect Tracing {
>         advice execution ("% ...::%(...)") : before () {
>                 std::cout << "in " << JoinPoint::signature() << std::endl;
>                 for (int i = 0; i < JoinPoint::ARGS; i++) {
>                         std::cout << (i ? ", " : "") << *tjp->arg<i>();
>                 }
>                 std::cout << std::endl;
>         }
> };
>
> When I run ag++ test.cpp, I get this error message:
>
> tracing.ah:8: error: no matching function for call to `arg'
> tracing.ah:8: error: invalid operand to unary `*'
> tracing.ah:8: error: invalid operand to binary `<<'
> tracing.ah:8: error: undefined type
> error: Execution failed: "ac++" --config "/tmp/agxx_pcfgdGZPhu"  -p. -c
> "test.cpp" -o "/tmp/test.cpp_agxx_v4z2Sl"
>
> If I leave the <i> part out, then I get a dereferencing void pointer error.
>
> Can someone help with fixing this?
>
> Regards,
> Sander
>
>
> _______________________________________________
> aspectc-user mailing list
> aspectc-user at aspectc.org
> http://www.aspectc.org/mailman/listinfo/aspectc-user




More information about the aspectc-user mailing list