AspectC++ in Action
- AOP
- Concept
- About the Project
- 示例 1 - Hello World
- 示例 2 - profiling
- AspectC++ – A Language Overview, May 20, 2005
- AspectC++ Quick Reference
- Documentation: Ag++ Manual
- Documentation: AC++ Compiler Manual, Version 2.3, February 17, 2021
- Documentation: AspectC++ Language Reference, Version 2.3, February 17, 2021
- Aspect-Oriented Programming with C++ and AspectC++, AOSD 2007 Tutorial
- The AspectC++ User Mailing List
- AspectC++ Frequently Asked Questions
- Problems & Workarounds
- Refer
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