diff options
-rw-r--r-- | src/sexpr/bind.cpp | 29 | ||||
-rw-r--r-- | src/sexpr/bind.hpp | 51 | ||||
-rw-r--r-- | src/sexpr/lexer.hpp | 2 | ||||
-rw-r--r-- | src/sexpr/parser.hpp | 2 | ||||
-rw-r--r-- | src/sexpr/union.cpp | 44 | ||||
-rw-r--r-- | src/sexpr/union.hpp | 108 | ||||
-rw-r--r-- | src/sexpr/variant.cpp | 40 | ||||
-rw-r--r-- | src/sexpr/variant.hpp | 119 | ||||
-rw-r--r-- | src/sexpr/variant.tcc | 293 | ||||
-rw-r--r-- | src/sexpr/variant_test.cpp | 125 | ||||
-rw-r--r-- | src/sexpr/void.cpp | 29 | ||||
-rw-r--r-- | src/sexpr/void.hpp | 43 |
12 files changed, 885 insertions, 0 deletions
diff --git a/src/sexpr/bind.cpp b/src/sexpr/bind.cpp new file mode 100644 index 0000000..d8d0caa --- /dev/null +++ b/src/sexpr/bind.cpp @@ -0,0 +1,29 @@ +#include "bind.hpp" +// bind.cpp - Just include the header file. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +namespace sexpr +{ +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/bind.hpp b/src/sexpr/bind.hpp new file mode 100644 index 0000000..7250f9d --- /dev/null +++ b/src/sexpr/bind.hpp @@ -0,0 +1,51 @@ +#ifndef TMWA_SEXPR_BIND_HPP +#define TMWA_SEXPR_BIND_HPP +// bind.hpp - Like std::bind, but with arbitrary arguments. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +# include <utility> + +# include "fwd.hpp" + + +namespace tmwa +{ +namespace sexpr +{ + template<class F, class T> + struct VariadicBind + { + // note: may be lvalue references + F&& f; + T&& t; + template<class... A> + auto operator()(A&&... a) -> decltype(std::forward<F>(f)(std::forward<T>(t), std::forward<A>(a)...)) + { + return std::forward<F>(f)(std::forward<T>(t), std::forward<A>(a)...); + } + }; + template<class F, class T> + VariadicBind<F, T> bind_variadic(F&& func, T&& arg1) + { + return VariadicBind<F, T>{std::forward<F>(func), std::forward<T>(arg1)}; + } +} // namespace sexpr +} // namespace tmwa + +#endif //TMWA_SEXPR_VARIANT_HPP diff --git a/src/sexpr/lexer.hpp b/src/sexpr/lexer.hpp index d1c4643..bd7b532 100644 --- a/src/sexpr/lexer.hpp +++ b/src/sexpr/lexer.hpp @@ -29,6 +29,8 @@ # include "../io/line.hpp" +# include "fwd.hpp" + namespace tmwa { diff --git a/src/sexpr/parser.hpp b/src/sexpr/parser.hpp index 2404a9a..c787e56 100644 --- a/src/sexpr/parser.hpp +++ b/src/sexpr/parser.hpp @@ -29,6 +29,8 @@ # include "lexer.hpp" +# include "fwd.hpp" + namespace tmwa { diff --git a/src/sexpr/union.cpp b/src/sexpr/union.cpp new file mode 100644 index 0000000..6f65012 --- /dev/null +++ b/src/sexpr/union.cpp @@ -0,0 +1,44 @@ +#include "union.hpp" +// union.cpp - Just include the header file and try to instantiate. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +namespace sexpr +{ +namespace +{ + struct Foo + { + Foo(); + Foo(const Foo&); + Foo& operator = (const Foo&); + ~Foo(); + }; +} // anonymous namespace +static Union<int, Foo> u; + +static_assert(u.index<int>() == 0, "int"); +static_assert(u.index<Foo>() == 1, "Foo"); +static_assert(u.index<char>() == size_t(-1), "char"); +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/union.hpp b/src/sexpr/union.hpp new file mode 100644 index 0000000..e0c3051 --- /dev/null +++ b/src/sexpr/union.hpp @@ -0,0 +1,108 @@ +#ifndef TMWA_SEXPR_UNION_HPP +#define TMWA_SEXPR_UNION_HPP +// union.hpp - A (unsafe!) convenience wrapper for classes in unions. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +# include <utility> +# include <type_traits> +# include <cstddef> +# include <new> + +# include "fwd.hpp" + + +namespace tmwa +{ +namespace sexpr +{ + template<class... T> + class Union; + + template<> + class Union<> + { + public: + template<class T> + constexpr static size_t index() + { + return -1; + } + Union() = default; + ~Union() = default; + Union(const Union&) = delete; + Union& operator = (const Union&) = delete; + }; + + template<class F, class... R> + class Union<F, R...> + { + static_assert(!std::is_const<F>::value, "union elements are not const"); + static_assert(!std::is_volatile<F>::value, "union elements are not volatile"); + static_assert(!std::is_reference<F>::value, "union elements are not references"); + static_assert(Union<R...>::template index<F>() == size_t(-1), "unions do not contain duplicates"); + union Impl + { + F first; + Union<R...> rest; + + Impl() {} + ~Impl() {} + } data; + public: + template<class T> + constexpr static size_t index() + { + return std::is_same<F, T>::value + ? 0 + : 1 + Union<R...>::template index<T>() + ?: -1; + } + template<class T> + void get(T*& p) { data.rest.get(p); } + void get(F*& p) { p = std::addressof(data.first); } + template<class T> + void get(const T*& p) const { data.rest.get(p); } + void get(const F*& p) const { p = std::addressof(data.first); } + + template<class T> + T *get() { T *out; get(out); return out; } + template<class T> + const T *get() const { const T *out; get(out); return out; } + + Union() = default; + ~Union() = default; + Union(const Union&) = delete; + Union& operator = (const Union&) = delete; + + template<class T, class... A> + void construct(A&&... a) + { + new (get<T>()) T(std::forward<A>(a)...); + } + + template<class T> + void destruct() + { + get<T>()->~T(); + } + }; +} // namespace sexpr +} // namespace tmwa + +#endif //TMWA_SEXPR_UNION_HPP diff --git a/src/sexpr/variant.cpp b/src/sexpr/variant.cpp new file mode 100644 index 0000000..b1f500a --- /dev/null +++ b/src/sexpr/variant.cpp @@ -0,0 +1,40 @@ +#include "variant.hpp" +// variant.cpp - Just include the header file. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +namespace sexpr +{ +namespace +{ + struct Foo + { + Foo() {} + ~Foo() {} + Foo(Foo&&) {} + Foo& operator = (Foo&&) { return *this; } + }; +} // anonymous namespace + static Variant<int, Foo> v; +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/variant.hpp b/src/sexpr/variant.hpp new file mode 100644 index 0000000..ccbfeaa --- /dev/null +++ b/src/sexpr/variant.hpp @@ -0,0 +1,119 @@ +#ifndef TMWA_SEXPR_VARIANT_HPP +#define TMWA_SEXPR_VARIANT_HPP +// variant.hpp - A single value, multiple type container. Better than boost's. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +# include <type_traits> +# include <cstdint> +# include <cstddef> +# include <utility> + +# include "union.hpp" +# include "void.hpp" + +# include "fwd.hpp" + + +namespace tmwa +{ +namespace sexpr +{ +# define JOIN(a, b) a##b + +# define WITH_VAR(ty, var, expr) \ + for (bool JOIN(var, _guard) = true; JOIN(var, _guard); ) \ + for (ty var = expr; JOIN(var, _guard); JOIN(var, _guard) = false) +# define MATCH(expr) \ + WITH_VAR(auto&&, _match_var, expr) \ + switch (tmwa::sexpr::VariantFriend::get_state(_match_var)) +# define CASE(ty, var) \ + break; \ + case tmwa::sexpr::VariantFriend::get_state_for<ty, decltype(_match_var)>(): \ + WITH_VAR(ty, var, tmwa::sexpr::VariantFriend::unchecked_get<ty>(_match_var)) + + template<class... T> + class Variant + { + static_assert(sizeof...(T), "A variant must not be empty"); + }; + template<class D, class... T> + class Variant<D, T...> + { + constexpr static size_t state_count = 1 + sizeof...(T); + + // simplify things immensely + friend class VariantFriend; + + typedef Union<D, T...> DataType; + DataType data; + size_t state; + + void do_destruct(); + template<class C, class... A> + void do_construct(A&&... a); + public: + Variant(); + ~Variant(); + + void reset(); + template<class C, class... A> + void emplace(A&&... a); + + Variant(const Variant& r); + Variant(Variant&& r); + Variant& operator = (const Variant& r); + Variant& operator = (Variant&& r); + + template<class E> + Variant(E e) + { + do_construct<E, E>(std::move(e)); + } + + template<class E> + Variant& operator = (E e) + { + emplace<E, E>(std::move(e)); + return *this; + } + + // use these ONLY if only one type makes sense + // otherwise use apply + template<class E> + bool is() const; + + template<class E> + E *get_if(); + + template<class E> + const E *get_if() const; + }; + + template<class R, class F> + void apply(R& r, F&& f); + template<class R, class F, class V1, class... V> + void apply(R& r, F&& f, V1&& v1, V&&... v); + template<class F, class... V> + void apply(Void&& r, F&& f, V&&... v); +} // namespace sexpr +} // namespace tmwa + +# include "variant.tcc" + +#endif //TMWA_SEXPR_VARIANT_HPP diff --git a/src/sexpr/variant.tcc b/src/sexpr/variant.tcc new file mode 100644 index 0000000..424a8f1 --- /dev/null +++ b/src/sexpr/variant.tcc @@ -0,0 +1,293 @@ +// variant.tcc - implementation of inlines and templates in variant.hpp +// +// Copyright © 2012-2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <cassert> +#include "bind.hpp" + +namespace tmwa +{ +namespace sexpr +{ + class VariantFriend + { + public: + template<class U, class... T, class... A> + static void unchecked_do_construct(Variant<T...> *var, A&&... a) + { + var->template do_construct<U, A...>(std::forward<A>(a)...); + } + template<class E, class... T> + static E& unchecked_get(Variant<T...>& var) + { + return *var.data.template get<E>(); + } + template<class E, class... T> + static const E& unchecked_get(const Variant<T...>& var) + { + return *var.data.template get<E>(); + } + template<class E, class... T> + static E&& unchecked_get(Variant<T...>&& var) + { + return std::move(*var.data.template get<E>()); + } + template<class E, class... T> + static const E&& unchecked_get(const Variant<T...>&& var) + { + return std::move(*var.data.template get<E>()); + } + + template<class E, class R, class F, class V1, class... V> + static void _apply_unchecked(R& r, F&& f, V1&& v1, V&&... v) + { + apply(r, bind_variadic(std::forward<F>(f), VariantFriend::unchecked_get<E>(std::forward<V1>(v1))), std::forward<V>(v)...); + } + + template<class... T, class R, class F, class V1, class... V> + static void _apply_dispatch(const Variant<T...> *, R& r, F&& f, V1&& v1, V&&... v) + { + typedef void (*Function)(R&, F&&, V1&&, V&&...); + constexpr static Function dispatch[sizeof...(T)] = { _apply_unchecked<T, R, F, V1, V...>... }; + assert(v1.state < sizeof...(T)); + dispatch[v1.state](r, std::forward<F>(f), std::forward<V1>(v1), std::forward<V>(v)...); + } + + template<class... T> + static size_t get_state(const Variant<T...>& variant) + { + return variant.state; + } + + template<class W, class V> + constexpr static size_t get_state_for() + { + return std::remove_reference<V>::type::DataType::template index<W>(); + } + }; + + + struct Destruct + { + template<class U> + void operator ()(U& v) + { + v.~U(); + } + }; + + template<class D, class... T> + void Variant<D, T...>::do_destruct() + { + apply(Void(), Destruct(), *this); + } + + template<class D, class... T> + template<class C, class... A> + void Variant<D, T...>::do_construct(A&&... a) + { + try + { + data.template construct<C, A...>(std::forward<A>(a)...); + state = Union<D, T...>::template index<C>(); + } + catch(...) + { + static_assert(std::is_nothrow_constructible<D>::value, "first element is nothrow constructible"); + data.template construct<D>(); + state = 0; + throw; + } + } + + template<class D, class... T> + Variant<D, T...>::Variant() + { + do_construct<D>(); + state = 0; + } + + template<class D, class... T> + Variant<D, T...>::~Variant() + { + do_destruct(); + } + + template<class D, class... T> + void Variant<D, T...>::reset() + { + do_destruct(); + do_construct<D>(); + } + + template<class D, class... T> + template<class C, class... A> + void Variant<D, T...>::emplace(A&&... a) + { + do_destruct(); + do_construct<C, A...>(std::forward<A>(a)...); + } + + template<class... T> + class CopyConstruct + { + Variant<T...> *target; + public: + CopyConstruct(Variant<T...> *v) : target(v) {} + template<class U> + void operator ()(const U& u) + { + VariantFriend::unchecked_do_construct<U>(target, u); + } + }; + template<class... T> + class MoveConstruct + { + Variant<T...> *target; + public: + MoveConstruct(Variant<T...> *v) : target(v) {} + template<class U> + void operator ()(U&& u) + { + VariantFriend::unchecked_do_construct<U>(target, std::move(u)); + } + }; + + // assignment requires unchecked access + template<class... T> + class CopyAssign + { + Union<T...> *data; + public: + CopyAssign(Union<T...> *d) : data(d) {} + template<class U> + void operator ()(const U& u) + { + *data->template get<U>() = u; + } + }; + + template<class... T> + class MoveAssign + { + Union<T...> *data; + public: + MoveAssign(Union<T...> *d) : data(d) {} + template<class U> + void operator () (U&& u) + { + *data->template get<U>() = std::move(u); + } + }; + + template<class D, class... T> + Variant<D, T...>::Variant(const Variant& r) + { + apply(Void(), CopyConstruct<D, T...>(this), r); + } + + template<class D, class... T> + Variant<D, T...>::Variant(Variant&& r) + { + apply(Void(), MoveConstruct<D, T...>(this), std::move(r)); + } + + template<class D, class... T> + Variant<D, T...>& Variant<D, T...>::operator = (const Variant& r) + { + if (state == r.state) + apply(Void(), CopyAssign<D, T...>(this), r); + else + { + do_destruct(); + apply(Void(), CopyConstruct<D, T...>(this), r); + } + return *this; + } + + template<class D, class... T> + Variant<D, T...>& Variant<D, T...>::operator = (Variant&& r) + { + if (state == r.state) + apply(Void(), MoveAssign<D, T...>(&data), std::move(r)); + else + { + do_destruct(); + apply(Void(), MoveConstruct<D, T...>(this), std::move(r)); + } + return *this; + } + + template<class D, class... T> + template<class E> + bool Variant<D, T...>::is() const + { + return get_if<E>(); + } + + template<class D, class... T> + template<class E> + E *Variant<D, T...>::get_if() + { + if (state == Union<D, T...>::template index<E>()) + return data.template get<E>(); + return nullptr; + } + + template<class D, class... T> + template<class E> + const E *Variant<D, T...>::get_if() const + { + if (state == Union<D, T...>::template index<E>()) + return data.template get<E>(); + return nullptr; + } + + template<class R, class F> + void _apply_assign(std::true_type, R& r, F&& f) + { + std::forward<F>(f)(); + r = Void(); + } + + template<class R, class F> + void _apply_assign(std::false_type, R& r, F&& f) + { + r = std::forward<F>(f)(); + } + + template<class R, class F> + void apply(R& r, F&& f) + { + _apply_assign(std::is_void<decltype(std::forward<F>(f)())>(), r, std::forward<F>(f)); + } + + template<class R, class F, class V1, class... V> + void apply(R& r, F&& f, V1&& v1, V&&... v) + { + VariantFriend::_apply_dispatch(&v1, r, std::forward<F>(f), std::forward<V1>(v1), std::forward<V>(v)...); + } + + template<class F, class... V> + void apply(Void&& r, F&& f, V&&... v) + { + apply(r, std::forward<F>(f), std::forward<V>(v)...); + } + +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/variant_test.cpp b/src/sexpr/variant_test.cpp new file mode 100644 index 0000000..1ecb82f --- /dev/null +++ b/src/sexpr/variant_test.cpp @@ -0,0 +1,125 @@ +#include "variant.hpp" +// variant_test.cpp - Testsuite for multi-type container that's better than boost's. +// +// Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include <gtest/gtest.h> + +#include "../strings/vstring.hpp" + +//#include "../poison.hpp" + + +namespace tmwa +{ +#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" + + struct Tracker + { + int id, moves, copies; + + explicit + Tracker(int i) + : id(i), moves(0), copies(0) + {} + Tracker(Tracker&& rhs) + : id(rhs.id), moves(rhs.moves + 1), copies(rhs.copies) + { rhs.id = 0; } + Tracker(const Tracker& rhs) + : id(rhs.id), moves(rhs.moves), copies(rhs.copies + 1) + {} + Tracker& operator = (Tracker&& rhs) + { id = rhs.id; moves = rhs.moves + 1; copies = rhs.copies; rhs.id = 0; return *this; } + Tracker& operator = (const Tracker& rhs) + { id = rhs.id; moves = rhs.moves; copies = rhs.copies + 1; return *this; } + }; + struct Foo : Tracker + { + // needed for first param of variant + Foo() noexcept : Tracker(0) { abort(); } + + Foo(int i) : Tracker(i) {} + }; + struct Bar : Tracker + { + Bar(int i) : Tracker(i) {} + }; + struct Qux : Tracker + { + // needed for first param of variant + Qux() noexcept : Tracker(0) { abort(); } + + Qux(int i) : Tracker(i) {} + Qux(Qux&&) = default; + Qux(const Qux&) = delete; + Qux& operator = (Qux&&) = default; + Qux& operator = (const Qux&) = default; + }; + +TEST(variant, match) +{ + struct Sub : sexpr::Variant<Foo, Bar> + { + Sub() + : sexpr::Variant<Foo, Bar>(Foo(1)) + {} + }; + Sub v1; + MATCH (v1) + { + // This is not a public API, it's just for testing. + default: + FAIL(); + + CASE(Foo, f) + { + (void)f; + SUCCEED(); + } + CASE(Bar, b) + { + (void)b; + FAIL(); + } + } + v1.emplace<Bar>(2); + MATCH (v1) + { + // This is not a public API, it's just for testing. + default: + FAIL(); + + CASE(Foo, f) + { + (void)f; + FAIL(); + } + CASE(Bar, b) + { + (void)b; + SUCCEED(); + } + } +} + +TEST(variant, copymove) +{ + sexpr::Variant<Qux> moveonly(Qux(3)); + (void)moveonly; +} +} // namespace tmwa diff --git a/src/sexpr/void.cpp b/src/sexpr/void.cpp new file mode 100644 index 0000000..9f0eeb5 --- /dev/null +++ b/src/sexpr/void.cpp @@ -0,0 +1,29 @@ +#include "void.hpp" +// void.cpp - Just include the header file. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +#include "../poison.hpp" + + +namespace tmwa +{ +namespace sexpr +{ +} // namespace sexpr +} // namespace tmwa diff --git a/src/sexpr/void.hpp b/src/sexpr/void.hpp new file mode 100644 index 0000000..9fb6bc4 --- /dev/null +++ b/src/sexpr/void.hpp @@ -0,0 +1,43 @@ +#ifndef TMWA_SEXPR_VOID_HPP +#define TMWA_SEXPR_VOID_HPP +// void.hpp - A type that represents nothing and anything. +// +// Copyright © 2012 Ben Longbons <b.r.longbons@gmail.com> +// +// This file is part of The Mana World (Athena server) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +# include "fwd.hpp" + + +namespace tmwa +{ +namespace sexpr +{ + struct Void + { + template<class T> + constexpr operator T() noexcept { return T(); } + template<class T> + void operator = (T&&) noexcept {} + template<class T> + constexpr Void(T&&) noexcept {} + constexpr Void() noexcept; + }; + constexpr Void::Void() noexcept = default; +} // namespace sexpr +} // namespace tmwa + +#endif //TMWA_SEXPR_VOID_HPP |