-
Notifications
You must be signed in to change notification settings - Fork 17
/
DeclareElseFilter.h
74 lines (65 loc) · 2.33 KB
/
DeclareElseFilter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#pragma once
#include "ContextMember.h"
#include "DeclareElseFilter.h"
#include "SatCounter.h"
template<class Base, class... Args>
class MicroElseFilter;
/// <summary>
/// Zero-argument specialization
/// </summary>
template<class Base>
class MicroElseFilter<Base> :
public ContextMember
{
public:
MicroElseFilter(Base* base, void (Base::*filter)(const AutoPacket&)) :
ContextMember("MicroElseFilter"),
base(base),
filter(filter)
{}
protected:
Base* base;
void (Base::*filter)(const AutoPacket&);
};
/// <summary>If Base::AutoFilter is not called, this will execute a Final-Call method</summary>
template<class Base, class Arg, class... Args>
class MicroElseFilter<Base, Arg, Args...>:
public MicroElseFilter<Base>
{
public:
MicroElseFilter(Base* base, void (Base::*filter)(const AutoPacket&)) :
MicroElseFilter<Base>(base, filter)
{}
void AutoFilter(const AutoPacket& packet) {
const bool has_all[] = {packet.Has<Arg>(), packet.Has<Args>()... };
for(bool cur : has_all)
if(!cur) {
// Missing decoration, base filter wasn't called
(this->base->*(this->filter))(packet);
return;
}
/// Base::AutoFilter has already been called for this packet
}
};
/// <summary>
/// Creates a MicroElseFilter to be called when the specified AutoFilter routine is not called
/// </summary>
/// <param name="testFilter">The filter whose state is to be tested when determining whether to call</param>
template<class Test, class Base, class... Args>
std::shared_ptr<MicroElseFilter<Base>> DeclareElseFilter(void(Test::*testFilter)(Args...), Base* that, void (Base::*filter)(const AutoPacket&)) {
AutoCurrentContext ctxt;
return ctxt->template Inject<MicroElseFilter<Base, Args...>>(that, filter);
}
/// <summary>
/// Creates a MicroElseFilter class that will call the method provided in the constructor
/// if and only if Base::AutoFilter has not been called.
/// </summary>
/// <remarks>
/// In the constructor of a class that will be Injected into a context call this function as:
/// DeclareElseFilter(this, &MyClass::ElseFilter)
/// </remarks>
template<class Base>
std::shared_ptr<MicroElseFilter<Base>> DeclareElseFilter(Base* that, void (Base::*filter)(const AutoPacket&)) {
return DeclareElseFilter(&Base::AutoFilter, that, filter);
}