neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
any_predicate.hpp
Go to the documentation of this file.
1// any_predicate.hpp
2/*
3 * Copyright (c) 2007 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
39#include <stdexcept>
40#include <typeinfo>
41
42namespace neolib
43{
44 template <typename T>
46 {
47 // types
48 public:
49 typedef T value_type;
50 struct bad_cast : public std::logic_error { bad_cast() : std::logic_error("neolib::any_predicate::bad_cast") {} };
51 struct no_predicate : public std::logic_error { no_predicate() : std::logic_error("neolib::any_predicate::no_predicate") {} };
52 private:
53 class holder_base
54 {
55 // construction
56 public:
57 virtual ~holder_base() = default;
58 // operations
59 public:
60 virtual bool operator()(const value_type& aLeft, const value_type& aRight) const = 0;
61 template <typename T>
62 operator const T&() const
63 {
64 if (typeid(T) != type())
65 throw bad_cast();
66 return *static_cast<const T*>(ptr());
67 }
68 template <typename T>
69 operator T&()
70 {
71 if (typeid(T) != type())
72 throw bad_cast();
73 return *static_cast<T*>(ptr());
74 }
75 template <typename T>
76 bool is() const { return typeid(T) == type(); }
77 virtual holder_base* clone() const = 0;
78 // implementation
79 private:
80 virtual const std::type_info& type() const = 0;
81 virtual const void* ptr() const = 0;
82 virtual void* ptr() = 0;
83 };
84 template <typename T>
85 class holder : public holder_base
86 {
87 // construction
88 public:
89 holder(const T& aObject) : iObject(aObject) {}
90 // implementation
91 private:
92 virtual bool operator()(const value_type& aLeft, const value_type& aRight) const { return iObject(aLeft, aRight); }
93 virtual holder_base* clone() const { return new holder(iObject); }
94 virtual const std::type_info& type() const { return typeid(T); }
95 virtual const void* ptr() const { return &iObject; }
96 virtual void* ptr() { return &iObject; }
97 // attributes
98 private:
99 T iObject;
100 };
101 // construction
102 public:
103 any_predicate() : iHolder(nullptr) {}
104 template <typename T>
105 any_predicate(const T& aObject) : iHolder(new holder<T>(aObject)) {}
106 any_predicate(const any_predicate& aOther) : iHolder(aOther.iHolder ? aOther.iHolder->clone() : nullptr) {}
107 ~any_predicate() { destroy(); }
109 {
110 destroy();
111 if (aOther.iHolder)
112 iHolder = aOther.iHolder->clone();
113 return *this;
114 }
115 // operations
116 public:
117 bool operator()(const value_type& aLeft, const value_type& aRight) const
118 {
119 if (empty())
120 throw no_predicate();
121 return (*iHolder)(aLeft, aRight);
122 }
123 template <typename T>
124 operator const T&() const { if (empty()) throw bad_cast(); return *iHolder; }
125 template <typename T>
126 operator T&() { if (empty()) throw bad_cast(); return *iHolder; }
127 template <typename T>
128 bool is() const { return iHolder && iHolder->is<T>(); }
129 bool something() const { return iHolder != nullptr; }
130 bool empty() const { return !something(); }
131 void reset() { destroy(); }
132 // implementation
133 private:
134 void destroy() { delete iHolder; iHolder = nullptr; }
135 // attributes
136 private:
137 holder_base* iHolder;
138 };
139}
any_predicate(const T &aObject)
any_predicate(const any_predicate &aOther)
any_predicate & operator=(const any_predicate &aOther)
bool operator()(const value_type &aLeft, const value_type &aRight) const