#include <stdio.h>
#include <iostream>

// from pugixml:

class xml_attribute {

protected:
    typedef void (*unspecified_bool_type)(xml_attribute***);

public:
    operator unspecified_bool_type() const;
    void use_op() {
        unspecified_bool_type b = (unspecified_bool_type)*this;
    }
};

xml_attribute::operator xml_attribute::unspecified_bool_type() const { return nullptr; }

// more kinds of proceed code

void v1() {}
const int r1() { return 1; }
volatile int r2() { return 2; }
const volatile int r3() { return 3; }
int *r4() { return (int*)0x12345; }
const int *r5() { return (int*)0x23456; }
const volatile int *r6() { return (int*)0x34567; }
int &p1() { static int a = 11; return a; }
const int &p2() { static int a = 12; return a; }
volatile int &p3() { static int a = 13; return a; }
const volatile int & p4() { static int a = 14; return a; }
// returning rvalue references is not implemented
// int &&r7() { static int i = 0; return (int&&)i; }

template <typename T> const char *qual(T &obj) { return "[]"; }
template <typename T> const char *qual(const T &obj) { return "[const]"; }
template <typename T> const char *qual(volatile T &obj) { return "[volatile]"; }
template <typename T> const char *qual(const volatile T &obj) { return "[const volatile]"; }
template <typename T> const char *qual(T* &obj) { return "[*]"; }
template <typename T> const char *qual(const T* &obj) { return "[const *]"; }
template <typename T> const char *qual(volatile T* &obj) { return "[volatile *]"; }
template <typename T> const char *qual(const volatile T* &obj) { return "[const volatile *]"; }

int main() {
    xml_attribute a;
    a.use_op();
    v1();
    r1();
    r2();
    r3();
    r4();
    r5();
    r6();
    p1();
    p2();
    auto res1 = p3(); // 'res1' to avoid warning
    auto res2 = p4();
}

aspect Test {
    advice execution("xml_attribute::operator %(...)") : around() {
        printf("before %s\n", JoinPoint::signature());
        tjp->proceed();
    }
    advice execution("void v%(...)")): around() {
        printf("before %s\n", JoinPoint::signature());
        tjp->proceed();
    }
    advice execution("% r%(...)" && !"%* r%(...)")): around() {
        printf("before %s\n", JoinPoint::signature());
        tjp->proceed();
        std::cout << "  r-result: " << *tjp->result() << " "
            << qual(*tjp->result()) << std::endl;
    }
    advice execution("%* r%(...)")): around() {
        printf("before %s\n", JoinPoint::signature());
        tjp->proceed();
        auto res = *tjp->result();
        // "cout <<" seems to have a problem with "const volatile*" printing
        std::cout << "  r-ptr-result: " << (void*)res << " "
            << qual(*tjp->result()) << std::endl;
    }
    advice execution("% p%(...)")): after() {
        printf("after %s\n", JoinPoint::signature());
        (*(int*)*tjp->result()) += 10;
        std::cout << "  p-result: " << **tjp->result() << " " 
            << qual(**tjp->result()) << std::endl;
    }
};
