AOP

AOP (Aspect-Oriented Programming, 面向切面编程),一个系统除了其自身的业务流程外,还需要有日志记录,性能统计,安全控制,事务处理,异常处理等等。AOP 通过预编译方式或运行期动态代理,把将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

  • 面向对象编程 (OOP) 是关注将需求功能划分为不同的并且相对独立,封装良好的类,并让它们有着属于自己的行为,依靠继承和多态等来定义彼此的关系。
  • 面向切面编程 (AOP) 是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。

OOP 实现了软件纵向的解耦合,AOP 实现了软件横向的解耦合。

Concept

AspectC++ is an aspect-oriented extension to the C++ language. (AspectC++ 是一个基于 C++ 的面向切面编程(AOP)框架,它可以帮助开发人员在不修改原有代码的情况下,通过切面来实现横切关注点的功能)

As ag++ is just a wrapper, it first generates the puma configuration file, then calls ac++ and afterwards g++.

The intermediate files generated by ac++ are stored in the directory which is extracted from the -o option or in current directory. In some cases this may lead to a situation where the names of intermediate files interfere with each other.

$cat puma.config
--skip-bodies-non-prj
-D __puma
-D __STDC__
-D "_GNU_SOURCE=1"
-D "_LP64=1"
-D "_STDC_PREDEF_H=1"
-D "__ATOMIC_ACQUIRE=2"
-D "__ATOMIC_ACQ_REL=4"
-D "__ATOMIC_CONSUME=1"
-D "__ATOMIC_HLE_ACQUIRE=65536"
-D "__ATOMIC_HLE_RELEASE=131072"
-D "__ATOMIC_RELAXED=0"
-D "__ATOMIC_RELEASE=3"
-D "__ATOMIC_SEQ_CST=5"
-D "__BIGGEST_ALIGNMENT__=16"
-D "__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__"
-D "__CHAR16_TYPE__=short unsigned int"
-D "__CHAR32_TYPE__=unsigned int"

...

-D "__cpp_variadic_templates=200704"
-D "__gnu_linux__=1"
-D "__has_include(STR)=__has_include__(STR)"
-D "__has_include_next(STR)=__has_include_next__(STR)"
-D "__k8=1"
-D "__k8__=1"
-D "__linux=1"
-D "__linux__=1"
-D "__unix=1"
-D "__unix__=1"
-D "__x86_64=1"
-D "__x86_64__=1"
-D "linux=1"
-D "unix=1"
--gnu 8.3.1

About the Project

The success of Aspect-Oriented Software Development rises and falls with user-friendly tool support. With AspectJ the first complete and powerful language extension for AOP has been created.

With the AspectC++ project we extend the AspectJ approach to C/C++. It is a set of C++ language extensions to facilitate aspect-oriented programming with C/C++. An implementation of an AspectC++ compiler is available for download from our download page.

示例 1 - Hello World

$tree
.
├── hello.h
├── main.cc
├── Makefile
└── world.ah
// main.cc

#include "hello.h"

int main(){
  hello(); //print "Hello"
  return 0;
}
// hello.h

#ifndef __HELLO_H__
#define __HELLO_H__

#include <iostream>

void hello() {
  std::cout << "Hello" << std::endl;
  //printf("hello\n");
}

#endif

world.ah 内容如下:

#ifndef __WORLD_AH__
#define __WORLD_AH__

#include <iostream>

aspect World {

  advice execution("void hello()") : after() {
    //print "World" after execution of the 'hello()' function
    std::cout << "World" << std::endl;
  }

};

#endif

Makefile 内容如下:

CXX ?= g++
ACXX ?= ag++

PROG:=$(shell basename $$PWD)

SOURCES := $(wildcard *.cc)

JUNK    := Junk
OBJECTS := $(addprefix $(JUNK)/,$(patsubst %.cc,%.o,$(SOURCES)))
DEPS    := $(addprefix $(JUNK)/,$(patsubst %.cc,%.d,$(SOURCES)))
HEADERS := $(wildcard *.h)
ASPECTS := $(wildcard *.ah)
INCLUDE_LIST := $(patsubst %.ah,-include %.ah,$(ASPECTS))

all: $(PROG)

run: all
        ./$(PROG)

$(PROG): $(OBJECTS)
        @echo Linking $@
        @$(CXX) $(CXXFLAGS) -o $@ $(OBJECTS) $(LDFLAGS)

clean:
        @rm -rf *.o $(JUNK) $(PROG)

$(JUNK)/%.o : %.cc
        @echo Compiling $<
        @$(ACXX) $(CXXFLAGS) --c_compiler clang++ -c $< -o $@

$(JUNK)/%.d : %.cc
        @mkdir -p $(JUNK)
        @$(CXX) $(CXXFLAGS) -MM $(INCLUDE_LIST) $< | \
        sed -e "s/$*\.o/$(JUNK)\/& $(JUNK)\/$*.d/g" > $@


ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif

.PHONY: clean all

# don't remove any intermediate files
.SECONDARY:

编译构建:

$make -n
echo Compiling main.cc
ag++ --c_compiler clang++ -c main.cc -o Junk/main.o
echo Linking helloworld
g++  -o helloworld Junk/main.o
$make
Compiling main.cc
Linking helloworld
$make run
./helloworld
Hello
World

示例 2 - profiling

$tree
.
├── genericprofiler.ah
├── main.cc
├── Makefile
└── profiler.ah
// main.cc

class MyClass {
private:
  void privateWork() {}
public:
  MyClass() {}
  void work() { for (int i=0; i<2; i++) privateWork(); }
  void work (int x) { for (int i=0; i<x; i++) work(); }

};


void work() {}
void nowork(int n, char** args) {}

int main() {
  MyClass obj;

  obj.work(3);

  work();
  work();

  return 0;
}

genericprofiler.ah

#ifndef __genericprofiler_ah__
#define __genericprofiler_ah__

#include <iostream>
#include <cstdlib>
using namespace std;


// GenericProfiler - generic aspect to gather profiling information
// (Name and signature of each executed function, how often the function
// was executed and how many clock cycles were spent executing it.)
//
// The following definitions need to be specialized:
//
//    pointcut virtual measureFct () = ... ;
//    Define a match expression for the functions to be profiled
//
//    virtual void (*summary())() { ... }
//    This function should return a pointer to a static function that
//    will be called when exiting the program.
//    If this function is not defined in a derived aspect, a simple
//    textual summary will be printed.
//    Refer to the function simple_stat() to learn how to access the
//    profiling data.
//
// This aspect uses the time stamp counter of the x86 processors
// to measure the execution time in clock cycles.
// When the profiling aspect should be used on other architectures
// the rdtsc() function and possibly the definition of the typedef
// ClockTicks and the function duration() must be replaced accordingly.



namespace Profiler {

  typedef unsigned long long int ClockTicks;

  // rdtsc() - read the time stamp counter of x86 processors
  extern inline ClockTicks rdtsc() {
    unsigned long long int x;
    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
    return x;
  }

  // duration() - calculate time spent between start and stop
  extern inline ClockTicks duration(ClockTicks start, ClockTicks end) {
    if (end > start) {
      return (end - start);
    } else { // counter overflow
      return (ClockTicks)(-1LL) - end + start;
    }
  }

  // Data structure used to gather the profiling information
  // New Data objects link themselves to existing ones at creation
  // time.
  struct Data {
    static Data *&first () { static Data *data = 0; return data; }
    struct Data *_next;
    unsigned _calls;
    ClockTicks _time;
    const char *_name;
    Data (const char* n) : _calls(0), _time(0L), _name (n) {
      Data *head = first ();
      first () = this;
      _next = head;
    }
  };

}


aspect GenericProfiler {

  // Do not measure the Profiler's own methods
  pointcut dontMeasure () = "% Profiler::...::%(...)" ||
    "% GenericProfiler::...::%(...)";

  // Pure virtual pointcut: to be specified in a derived aspect
  pointcut virtual measureFct () = 0;

  // Execution advice for the functions that are to be measured.
  // For each JoinPoint the advice code will be transformed into
  // a new template function instantiation. Therefore a new Data object
  // will be created whenever a function is executed the first time.
  // Further executions of the same function will reuse this object,
  // enabling it to count the number of invocations and the overall
  // time consumed.
  advice execution(measureFct() && !dontMeasure()) : around() {
    static Profiler::Data data (JoinPoint::signature ());
    Profiler::ClockTicks start = Profiler::rdtsc();
    tjp->proceed();
    Profiler::ClockTicks end = Profiler::rdtsc();
    data._calls++;
    data._time += Profiler::duration (start, end);
  };

  // Print a simple summary
  static void simple_stat () {
    cout << "Statistics:" << endl;
    for (Profiler::Data *curr = Profiler::Data::first ();
         curr; curr = curr->_next) {
      cout << "---" << endl;
      cout << "function:    " << curr->_name << endl;
      cout << "no of execs: " << curr->_calls << endl;
      cout << "total time:  " << curr->_time << endl;
    }
  }

  // Return the function that should be used to print the profiling summary
  // Specialize this function if you prefer a different kind of output.
  virtual void (*summary())() {
    return &simple_stat;
  }

  // This advice is used to register the function that prints the summary
  // to be executed when the program exits.
  advice execution ("% main(...)") : after () {
    atexit (summary());
  }
};


#endif

profiler.ah

#ifndef __profiler_ah__
#define __profiler_ah__

#include "genericprofiler.ah"
#include <iostream>
using namespace std;


//------------------------------------------------------------
// Specialized profiling aspect
//
// Here the specialization is used to add all functions
// to the profiling and to replace the default summary by a summary
// that uses the csv format

aspect CSVProfiler : public GenericProfiler {

  // Gather profiling information for all functions
  pointcut virtual measureFct () = "% ...::% (...)" &&
    !"% CSVProfiler::%(...)";


  // Print summary using the csv format
  static void csv_stat () {
    cout << "function ; number of executions ; total time (clock cycles)"
         << endl;
    for (Profiler::Data *curr = Profiler::Data::first ();
         curr; curr = curr->_next) {
      cout << curr->_name << " ; "
           << curr->_calls << " ; "
           << curr->_time << endl;
    }
  }

  // Register the specialized function that prints the summary
  virtual void (*summary())() {
    return &csv_stat;
  }

};

#endif

编译构建:

$make -n
echo Compiling main.cc
ag++  --c_compiler clang++ -c main.cc -o Junk/main.o
echo Linking profiling
g++  -o profiling Junk/main.o

运行:

$./profiling
function ; number of executions ; total time (clock cycles)
void work() ; 2 ; 78
void MyClass::privateWork() ; 6 ; 234
void MyClass::work() ; 3 ; 858
void MyClass::work(int) ; 1 ; 1300
int main() ; 1 ; 2392

AspectC++ – A Language Overview, May 20, 2005

The overview is based on the documentation for AspectC++ 0.9.3. The language is still “work in progress”.

AspectC++ Quick Reference

Aspects are modular implementations of crosscutting(横切) concerns. They can affect join points in the component code, e.g. class definitions, or in the dynamic control flow, e.g. function calls, by advice. A set of related join points is called pointcut(切入点) and defined by a pointcut expression.

Advice Language and Joinpoint API

The advice body is implemented in standard C++. Additionally, the joinpoint API can be used to access (read and write) context information (e.g. function argument and result values) as well as static type information about the current joinpoint.

To access the joinpoint API the object JoinPoint *tjp can be used, which is implicitly available in advice code. Advice that uses the static type information provided by the joinpoint API is called generic advice.

This concept is the key for generic, type-safe, and efficient advice in AspectC++. The static type information from the joinpoint API can even be used to instantiate template metaprograms, which is a technique for joinpoint specific code generation at compile time.

The joinpoint API is also used to proceed the execution from within around advice (tjp->proceed()). Alternatively, tjp->action() may be called to retrieve and store the proceed context as an AC::Action object. Later, action.trigger() may be called to proceed the intercepted flow of control.

Catching and changing exceptions can be done by standard C++ features in around advice (try, catch, throw).

Example

The following advice is generic advice, because its implementation can deal with multiple overloaded C::foo(...) implementations that have different result types:

advice execution(" % C::foo(...)") : around() {
    std::cout << " executing " << JoinPoint::signature() << " on " << *tjp->that() << std::endl ;
    tjp-> proceed();
    std::cout << " the result was " << *tjp->result() << std::endl ;
}

Documentation: Ag++ Manual

The ag++ program provides a more intuitive(使用简便的) frontend to the AspectC++ weaver (ac++) in a GNU environment. The only preliminaries are a working installation of GNU C++ compiler, which also can run within a cygwin environment. It basically wraps the functionality of the aspect weaver and the c++ compiler into one single program.

$ag++ --help
usage:  ag++ [options] [file...]
   options are ...
     --gen_config               Only generate Puma configuration file
     --weave_only               Weave only
     -c                         Compile only
     --keep_woven               Keep woven source code files
     --keep_acc                 Deprecated. Use keep_woven instead
     --c_compiler <arg>         Path to C++ compiler
     --ac_compiler <arg>        Path to AspectC++ compiler
     -o|--output <arg>          Name of the output file
     --config_command <arg>     Command which prints information about compiler
     --Xcompiler                In case of doubt account following options as g++ options
     --Xweaver                  In case of doubt account following options as ac++ options
     -h|--help                  Print this help meassage
     --version                  Version information
     -v|--verbose <arg>         Level of verbosity (0-9)
     -i|--include_files         Generate manipulated header files
     -a|--aspect_header <arg>   Name of aspect header file or '0'
     -r|--repository <arg>      Name of the project repository
     --expr <arg>               Pointcut expression to match in repository
     --problem_local_class      Back-end does not support local classes correctly
     --no_problem_local_class   Back-end supports local classes correctly
     --problem_spec_scope       Back-end does not support template specialization in non-namespace
     --no_problem_spec_scope    Back-end supports template specialization in non-namespace scope
     --problem_force_inline     Back-end does not support forced inlining correctly
     --no_problem_force_inline  Back-end supports forced inlining correctly
     --warn_deprecated          Warn if deprecated syntax is used
     --no_warn_deprecated       Don't warn if deprecated syntax is used
     --warn_macro               Warn if a macro transformation had to be ignored
     --no_warn_macro            Don't warn if a macro transformation had to be ignored
     --warn_limitations         Warn if a feature does not work as familiar due to limitations
     --no_warn_limitations      Don't warn if a feature does not work as familiar due to limitations
     --no_line                  Don't generate #line directives
     --gen_size_type <arg>      Argument type for generated new operator
     --real-instances           Perform full template analysis
     --pseudo-instances         Simplified template instantiation scheme (deprecated)
     -p|--path <arg>            Path to project source
     -d|--dest <arg>            Path to destination for modified include files
     --config <arg>             Full path to a config file
     --system-config <arg>      Full path to a system config file (lower priority options)
     --target <arg>             Override the compiler's target triple
     -I <arg>                   Add new include path
     -isysroot <arg>                    Specify isysroot path
     -F <arg>                   Add new framework include path
     -D <arg>                   Define a preprocessor macro
     -U <arg>                   Undefine a preprocessor macro
     -include|--include <arg>   Always include file
     -k|--keywords              Allow AspectC++ keywords in normal project files
     --dynamic                  Prepare generated code for dynamic weaving
     --introspection            Support introspection mechanism
     --flow_analysis            Support control-flow analysis and data-flow analysis
     --builtin_operators        Support joinpoints on builtin operator calls
     --data_joinpoints          Support data-based joinpoints like get(), set(), ...
     --attributes               Support user-defined attributes
     --no_attributes            Disable support user-defined attributes
     -isystem <arg>             Add system include path
     --warn_compatibility <arg>         Enable migration warnings for code based on major version <arg>

Documentation: AC++ Compiler Manual, Version 2.3, February 17, 2021

The program ac++ is a compiler for the AspectC++ programming language. It is implemented as a preprocessor that transforms AspectC++ code into ordinary C++ code.

During this transformation aspect code, which is defined by aspects, is woven statically into the component code.

Aspects are a special AspectC++ language element, which can be used to implement crosscutting(横切) concerns in separate modules.

Aspect definitions have to be implemented in special “aspect header files”, which normally have the filename extension *.ah.

After the code transformation the output of ac++ can be compiled to executable code with ordinary C++ compilers like GNU g++, or Microsoft VisualC++.

$ac++ -h
usage: ac++ options
   options are ...
     -p|--path <arg>            project directory tree
     -d|--dest <arg>            target directory tree
     -e|--extension <arg>       translation unit filename ext.
     -V|--version               Version information
     -h|--help                  Get this help text
     -v|--verbose <arg>         Level of verbosity (0-9)
     -c|--compile <arg>         Name of the input file
     -o|--output <arg>          Name of the output file
     -i|--include_files         Generate manipulated header files
     -a|--aspect_header <arg>   Name of aspect header file or '0'
     -r|--repository <arg>      Name of the project repository
     -x|--expr <arg>            Pointcut expression to match in repository
     --problem_local_class      Back-end does not support local classes correctly
     --no_problem_local_class   Back-end supports local classes correctly
     --problem_spec_scope       Back-end does not support template specialization in non-namespace
     --no_problem_spec_scope    Back-end supports template specialization in non-namespace scope
     --problem_force_inline     Back-end does not support forced inlining correctly
     --no_problem_force_inline  Back-end supports forced inlining correctly
     --no_line                  Don't generate #line directives
     --gen_size_type <arg>      Argument type for generated new operator
     --proj_file <arg>          Path to the project file
     --warn_deprecated          Warn if deprecated syntax is used
     --no_warn_deprecated       Don't warn if deprecated syntax is used
     --warn_macro               Warn if a macro transformation had to be ignored
     --no_warn_macro            Don't warn if a macro transformation had to be ignored
     --warn_limitations         Warn if a feature does not work as familiar due to limitations
     --no_warn_limitations      Don't warn if a feature does not work as familiar due to limitations
     -k|--keywords              Allow AspectC++ keywords in normal project files
     --dynamic                  Prepare generated code for dynamic weaving
     --introspection            Support introspection mechanism
     --flow_analysis            Support control-flow analysis and data-flow analysis
     --builtin_operators        Support joinpoints on builtin operator calls
     --data_joinpoints          Support data-based joinpoints like get(), set(), ...
     --introduction_depth <arg> Set the maximum depth for nested introductions
     --warn_compatibility <arg> Enable migration warnings for code based on major version <arg>
     --attributes               Support user-defined attributes
     --no_attributes            Disable support user-defined attributes
   further options for correct parsing are ...
     -I <arg>                   include file search path
     -D <name>[=<value>]        macro definitions

Download and Installation

Binaries of ac++ for various platforms are available for free download from the AspectC++ homepage.

Besides the archive file with the compiler there is a README file and a CHANGELOG file available for each release.

The README file explains the necessary steps for the installation, while the CHANGELOG documents the changes in the corresponding release as well as the history of changes.

https://www.aspectc.org/releases/2.3/README-2.3

Installation
------------

Installation on systems with g++ is straightforward. Unpack the tarball,
enter the created directory "aspectc++" and you are ready to
test the examples.


Examples
--------

To play with the examples type "make" in the top level directory to
run ac++ on the examples under the examples/ directory. After that,
the examples are automatically executed. To run a specific example,
change to the directory and type "make run" to start the generated binary.


Documentation
-------------

The documentation for AspectC++ can be downloaded at http://www.aspectc.org.
There are serveral manuals from a brief AspectC++ language overview to
detailed compiler descriptions.


Contact
-------

Visit http://www.aspectc.org for more information and updated versions.

If you want any information about the AspectC++ project or have any comments,
feel free to send us mail via info@aspectc.org.

Invocation

The ac++ compiler supports two major transformation modes:

Whole Program Transformation (WPT)

WPT mode was the first transformation mode of ac++. However, it is not obsolete, because it may be useful in many cases.

In this mode ac++ transforms all files in a project directory tree (or set of directories) and saves the result in a different directory tree. For each translation unit and header file a new file is generated in the target tree with the same name.

If further transformations of the source code have to be done, either with ac++ or other tools, this is the mode to choose. Even comments and whitespace remain untouched.

Single Translation Unit (STU)

In the STU mode ac++ must be called once for each translation unit like a normal C++ compiler. This makes it easier to integrate ac++ into Makefiles or IDEs.

As ac++ can’t save manipulated header files in this mode, because the unchanged header files are needed for the next translation units, all #include directives in the translation unit that refer to header files of the project directory tree are expanded and, thus, saved together with the manipulated translation unit. The resulting files can be fed directly into a C++ compiler. They do not depend on any other files of the project anymore.

Documentation: AspectC++ Language Reference, Version 2.3, February 17, 2021

This document is intended to be used as a reference book for the AspectC++ language elements. It describes in-depth the use and meaning of each element providing examples. For experienced users the contents of this document are summarized in the AspectC++ Quick Reference. Detailed information about the AspectC++ compiler ac++ can be looked up in the AspectC++ Compiler Manual.

Basic Concepts

Pointcuts (切入点)

Aspects in AspectC++ implement crosscutting concerns in a modular way. With this in mind the most important element of the AspectC++ language is the pointcut.

Pointcuts describe a set of join points by determining on which condition an aspect shall take effect. Thereby each join point can either refer to a function, a type/class, a variable, or a point from which a join point is accessed so that this condition can be for instance the event of reaching a designated code position or the allocation of a variable with a certain value. Depending on the kind of pointcuts, they are evaluated at compile time or at runtime.

There are two types of pointcuts in AspectC++: code pointcuts and name pointcuts.

Name pointcuts describe a set of (statically) known program entities like types/classes, variables, functions, or namespaces. All name pointcuts are based on match expressions.

Match Expressions (name pointcuts)

Match expressions select program entities with respect to their definition scope, their type, and their name.

A match expression can be understood as a search pattern.

In such a search pattern the special character % is interpreted as a wildcard for names or parts of a signature.

The special character sequence ... matches any number of parameters in a function signature or any number of scopes in a qualified name.

A match expression is a quoted string.

Example: match expressions (name pointcuts)

"int C::%(...)"

matches all member functions of the class C that return an int

"%List"

matches any namespace, class, struct, union, or enum whose name ends with List.

"% printf(const char *, ...)"

matches the function printf (defined in the global scope) having at least one parameter of type const char * and returning any type

"const %& ...::%(...)"

matches all functions that return a reference to a constant object

Pointcut Expressions (code pointcuts)

The other type of pointcuts, the code pointcuts, describe an intersection through the set of the points in the control flow of a program.

A code pointcut can refer to a call or execution point of a function, to a call of a built-in operator or and to write and read points of member variables and global variables.

They can only be created with the help of name pointcuts because all join points supported by AspectC++ require at least one name to be defined. This is done by calling predefined pointcut functions in a pointcut expression that expect a pointcut as argument.

Such a pointcut function is for instance within(pointcut), which filters all join points that are within the functions or classes in the given pointcut.

Name and code pointcuts can be combined in pointcut expressions by using the algebraic operators &&, ||, and !.

Example: pointcut expressions

"%List" && !derived("Queue")

describes the set of classes with names that end with List and that are not derived from the class Queue

call("void draw()") && within("Shape")

describes the set of calls to the function draw that are within methods of the class Shape

Aspect-Oriented Programming with C++ and AspectC++, AOSD 2007 Tutorial

The AspectC++ User Mailing List

From Getting started with AspectC++

I’m the AspectC++ project leader. If you need help, the best way is to subscribe to the AspectC++ user mailing list (visit www.aspectc.org and click on “support”) and post a question there. It is not possible to be aware of all questions being posted anywhere on the web. Sorry. Yet, you are really welcome on our mailing list!

https://www.aspectc.org/mailman/listinfo/aspectc-user

This mailing list is used for discussions of AspectC++ users and developers about features, bugs, and anythings else around the language.

To see the collection of prior postings to the list, visit the aspectc-user Archives.

AspectC++ Frequently Asked Questions

My pointcut expression matching a function looks perfect, but ac++ doesn’t weave my advice code. Why?

Make sure that the matched name is not a macro. AspectC++ can’t match macros:

#define X x_is_real_function_name

// ...

int X(int b) { ... }

will not be matched by “% X(int)”.

What about weaving in templates?

ac++ does not support weaving in templates yet. These potential join-points are silently ignored by the match mechanism.

The reason is that weaving in templates requires a full syntactic and semantic analysis of the template instances by the underlying C++ parser. However, this parser feature is still experimental and does not work for real-world code. Once the parser is able to perform this analysis reliably, we can implement the necessary code transformations within the aspect weaver.

Problems & Workarounds

Back-End Compiler Support

参考 4.2 Back-End Compiler Support

The C++ compiler that should be used to compile the output of ac++ (back-end compiler) plays a very important role for ac++, because compilers normally come with header files, which ac++ must be able to parse.

None of the back-end compilers listed here has totally standard conforming header files, which makes it very hard for ac++ to parse all this code.

GNU g++ (including Cygwin/GNU g++ under Windows) and clang++ are our best supported compilers.

Users of clang++ can invoke it via ag++ by using the ag++ option --c_compiler clang++.

Templates

Currently ac++ is able to parse a lot of the (really highly complicated) C++ templates, but weaving is restricted to non-templated code only. That means you can not weave in templates or even affect calls to template functions or members of template classes. However, template instances can be matched by match expressions in the pointcut language and calls to members of class templates or template functions can be affected by advice.

AspectC++ 能够解析大部分复杂的 C++ 模板,但是切面编织(weaving)只能应用于非模板代码。也就是说,不能在模板代码中编织切面,也不能影响对模板函数或模板类成员的调用。但是,可以使用匹配表达式(match expressions)在切入点语言中匹配模板实例,并使用通知(advice)影响对类模板成员或模板函数的调用。

Functions with variable argument lists

There is no support for execution advice on functions with variable argument lists. A warning will be issued. There is no portable way to generate a wrapper function for this class of functions.

Restrictions on calling tjp->proceed()

Due to a problem with result object construction/destruction of intercepted functions, the tjp->proceed() function may only be called once during around advice.

Refer

  • AspectC++ Wikipedia
  • https://www.aspectc.org/Home.php
  • https://www.aspectc.org/Documentation.php