AOP C++通用模板实现

has_member.h:

#ifndef __AOP_SRC_HAS_MEMBER_H__
#define __AOP_SRC_HAS_MEMBER_H__
#include

#define HAS_MEMBER_FUNCTION(member) \
template \
struct has_member_##member \
{ \
private: \
    template \
    static auto test(void*) -> decltype(std::declval().member(std::declval()...), std::true_type()); \
    \
    template\
    static std::false_type test(...);\
    \
public:\
    static const bool value = decltype(test(nullptr))::value;\
};

#endif

macros.h:

#ifndef __AOP_MACROS_H__
#define __AOP_MACROS_H__

#define AOP_NAMESPACE_BEGIN namespace aop {

#define AOP_NAMESPACE_END }

#endif

aspect.h:

#ifndef __AOP_SRC_ASPECT_H__
#define __AOP_SRC_ASPECT_H__
#include "has_member.h"
#include "macros.h"

AOP_NAMESPACE_BEGIN

HAS_MEMBER_FUNCTION(Before);
HAS_MEMBER_FUNCTION(After);

template
struct Aspect
{
    Aspect(Func&& func) : func_(std::forward(func)) {}
    Aspect(const Aspect&) = delete;
    Aspect& operator=(const Aspect&) = delete;

    template::value>>
    void InvokeBefore(T&& aspect, Args&&... args)
    {
        aspect.Before(std::forward(args)...);
    }

    void InvokeBefore(...) {}

    template::value>>
    void InvokeAfter(T&& aspect, Args&&... args)
    {
        aspect.After(std::forward(args)...);
    }

    void InvokeAfter(...) {}

    template
    void Invoke(Args&&... args, T&& aspect)
    {
        InvokeBefore(std::forward(aspect), std::forward(args)...);
        func_(std::forward(args)...);
        InvokeAfter(std::forward(aspect), std::forward(args)...);
    }

    template
    void Invoke(Args&&... args, Head&& head, Tail&&... tail)
    {
        InvokeBefore(std::forward(head), std::forward(args)...);
        Invoke(std::forward(args)..., std::forward(tail)...);
        InvokeAfter(std::forward(head), std::forward(args)...);
    }

private:
    Func func_;
};

template
using identity_t = typename std::identity::type;

template
void Invoke(Func&& func, Args&&... args)
{
    Aspect asp(std::forward(func));
    asp.Invoke(std::forward(args)..., identity_t()...);
}

template
void InvokeWithAspects(AP&&...ap, Func&& func, Args&&... args)
{
    Aspect asp(std::forward(func));
    asp.Invoke(std::forward(args)..., std::forward(ap)...);
}

AOP_NAMESPACE_END

#endif

test:

 

// aop.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include
#include
#include
#include "has_member.h"
#include "aspect.h"

using namespace std;

struct TimeElapsedAspect
{
    void Before(int i)
    {
        std::cout << "start timer" << std::endl;
        timer = std::chrono::system_clock::now();
    }

    void After(int i)
    {
        cout << "time elapsed: " << std::chrono::system_clock::duration(std::chrono::system_clock::now() - timer).count() << endl;
    }

private:
    std::chrono::system_clock::time_point timer{ std::chrono::system_clock::now() };
};

struct LoggingAspect
{
    LoggingAspect()
    {
        static int id = 0;
        std::cout << "LoggingAspect::construct -- id:" << id++ << std::endl;
    }

    void Before(int i)
    {
        std::cout << "entering" << std::endl;
    }

    void After(int i)
    {
        std::cout << "leaving" << std::endl;
    }
};

struct NoBeforeOrAfter
{
    NoBeforeOrAfter()
    {
        static int id = 0;
        std::cout << "NoBeforeOrAfter::construct -- id:" << id++ << std::endl;
    }

    void Before(const std::string&)
    {
    }

    void After(const std::string&)
    {
    }
};

void foo(int a)
{
    cout << "real HT function: " << a << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{

    aop::Invoke(&foo, 1);
    cout << "-----------------------" << endl;
    aop::Invoke(&foo, 1);
    cout << "-----------------------" << endl;
    aop::Invoke(&foo, 1);
    cout << "-----------------------" << endl;

    LoggingAspect logging;
    TimeElapsedAspect timer;
    NoBeforeOrAfter no_before_or_after;

    aop::InvokeWithAspects(std::forward(logging),
        std::forward(logging),
        std::forward(timer),
        std::forward(no_before_or_after),
        &foo, 1);

    system("pause");

    return 0;
}

 

你可能感兴趣的:(C/C++)