d
This commit is contained in:
553
v4/1
Normal file
553
v4/1
Normal file
@@ -0,0 +1,553 @@
|
||||
/**
|
||||
* Implementation of N4562 std::experimental::any (merged into C++17 as std::any)
|
||||
* for C++11 compilers.
|
||||
*
|
||||
* See also:
|
||||
* + http://en.cppreference.com/w/cpp/any
|
||||
* + http://en.cppreference.com/w/cpp/experimental/any
|
||||
* + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4562.html#any
|
||||
* + https://cplusplus.github.io/LWG/lwg-active.html#2509
|
||||
*
|
||||
* Copyright (c) 2016 Denilson das Merc?s Amorim
|
||||
* Copyright (c) 2018 Claudio Fantacci
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE.md or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef ANY_H
|
||||
#define ANY_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace libany
|
||||
{
|
||||
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "bad any_cast";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class any final
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs an object of type any with an empty state.
|
||||
*/
|
||||
any() :
|
||||
vtable(nullptr)
|
||||
{ }
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an object of type any with an equivalent state as other.
|
||||
*/
|
||||
any(const any& rhs) :
|
||||
vtable(rhs.vtable)
|
||||
{
|
||||
if(rhs.has_value())
|
||||
{
|
||||
rhs.vtable->copy(rhs.storage, this->storage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an object of type any with a state equivalent to the original state of other.
|
||||
* rhs is left in a valid but otherwise unspecified state.
|
||||
*/
|
||||
any(any&& rhs) noexcept :
|
||||
vtable(rhs.vtable)
|
||||
{
|
||||
if(rhs.has_value())
|
||||
{
|
||||
rhs.vtable->move(rhs.storage, this->storage);
|
||||
rhs.vtable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same effect as this->clear().
|
||||
*/
|
||||
~any()
|
||||
{
|
||||
this->reset();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an object of type any that contains an object of type T direct-initialized with std::forward<ValueType>(value).
|
||||
* T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed.
|
||||
* This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed.
|
||||
*/
|
||||
template<typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, any>::value>::type>
|
||||
any(ValueType&& value)
|
||||
{
|
||||
static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
|
||||
"T shall satisfy the CopyConstructible requirements.");
|
||||
this->construct(std::forward<ValueType>(value));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Has the same effect as any(rhs).swap(*this). No effects if an exception is thrown.
|
||||
*/
|
||||
any& operator=(const any& rhs)
|
||||
{
|
||||
any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Has the same effect as any(std::move(rhs)).swap(*this).
|
||||
* The state of *this is equivalent to the original state of rhs and rhs is left in a valid
|
||||
* but otherwise unspecified state.
|
||||
*/
|
||||
any& operator=(any&& rhs) noexcept
|
||||
{
|
||||
any(std::move(rhs)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Has the same effect as any(std::forward<ValueType>(value)).swap(*this). No effect if a exception is thrown.
|
||||
* T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed.
|
||||
* This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed.
|
||||
*/
|
||||
template<typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, any>::value>::type>
|
||||
any& operator=(ValueType&& value)
|
||||
{
|
||||
static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value, "T shall satisfy the CopyConstructible requirements.");
|
||||
any(std::forward<ValueType>(value)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If not empty, destroys the contained object.
|
||||
*/
|
||||
void reset() noexcept
|
||||
{
|
||||
if(has_value())
|
||||
{
|
||||
this->vtable->destroy(storage);
|
||||
this->vtable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if *this has no contained object, otherwise false.
|
||||
*/
|
||||
bool has_value() const noexcept
|
||||
{
|
||||
return this->vtable != nullptr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If *this has a contained object of type T, typeid(T); otherwise typeid(void).
|
||||
*/
|
||||
const std::type_info& type() const noexcept
|
||||
{
|
||||
return has_value()? this->vtable->type() : typeid(void);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exchange the states of *this and rhs.
|
||||
*/
|
||||
void swap(any& other) noexcept
|
||||
{
|
||||
if(this->vtable != other.vtable)
|
||||
{
|
||||
any tmp(std::move(other));
|
||||
|
||||
other.vtable = this->vtable;
|
||||
if(this->vtable != nullptr)
|
||||
this->vtable->move(this->storage, other.storage);
|
||||
|
||||
this->vtable = tmp.vtable;
|
||||
if(tmp.vtable != nullptr)
|
||||
{
|
||||
tmp.vtable->move(tmp.storage, this->storage);
|
||||
tmp.vtable = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(this->vtable != nullptr)
|
||||
this->vtable->swap(this->storage, other.storage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
union storage_union
|
||||
{
|
||||
using stack_storage_t = typename std::aligned_storage<2 * sizeof(void*), std::alignment_of<void*>::value>::type;
|
||||
|
||||
void* dynamic;
|
||||
|
||||
stack_storage_t stack;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Base VTable specification.
|
||||
*
|
||||
* Note: The caller is responsible for doing .vtable = nullptr after destructful operations
|
||||
* such as destroy() and/or move().
|
||||
*/
|
||||
struct vtable_type
|
||||
{
|
||||
/**
|
||||
* The type of the object this vtable is for.
|
||||
*/
|
||||
const std::type_info& (*type)() noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Destroys the object in the union.
|
||||
* The state of the union after this call is unspecified, caller must ensure not to use src anymore.
|
||||
*/
|
||||
void(*destroy)(storage_union&) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Copies the **inner** content of the src union into the yet unitialized dest union.
|
||||
* As such, both inner objects will have the same state, but on separate memory locations.
|
||||
*/
|
||||
void(*copy)(const storage_union& src, storage_union& dest);
|
||||
|
||||
|
||||
/**
|
||||
* Moves the storage from src to the yet unitialized dest union.
|
||||
* The state of src after this call is unspecified, caller must ensure not to use src anymore.
|
||||
*/
|
||||
void(*move)(storage_union& src, storage_union& dest) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Exchanges the storage between lhs and rhs.
|
||||
*/
|
||||
void(*swap)(storage_union& lhs, storage_union& rhs) noexcept;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* VTable for dynamically allocated storage.
|
||||
*/
|
||||
template<typename T>
|
||||
struct vtable_dynamic
|
||||
{
|
||||
static const std::type_info& type() noexcept
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
|
||||
static void destroy(storage_union& storage) noexcept
|
||||
{
|
||||
delete reinterpret_cast<T*>(storage.dynamic);
|
||||
}
|
||||
|
||||
|
||||
static void copy(const storage_union& src, storage_union& dest)
|
||||
{
|
||||
dest.dynamic = new T(*reinterpret_cast<const T*>(src.dynamic));
|
||||
}
|
||||
|
||||
|
||||
static void move(storage_union& src, storage_union& dest) noexcept
|
||||
{
|
||||
dest.dynamic = src.dynamic;
|
||||
src.dynamic = nullptr;
|
||||
}
|
||||
|
||||
|
||||
static void swap(storage_union& lhs, storage_union& rhs) noexcept
|
||||
{
|
||||
std::swap(lhs.dynamic, rhs.dynamic);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* VTable for stack allocated storage.
|
||||
*/
|
||||
template<typename T>
|
||||
struct vtable_stack
|
||||
{
|
||||
static const std::type_info& type() noexcept
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
|
||||
static void destroy(storage_union& storage) noexcept
|
||||
{
|
||||
reinterpret_cast<T*>(&storage.stack)->~T();
|
||||
}
|
||||
|
||||
|
||||
static void copy(const storage_union& src, storage_union& dest)
|
||||
{
|
||||
new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
|
||||
}
|
||||
|
||||
|
||||
static void move(storage_union& src, storage_union& dest) noexcept
|
||||
{
|
||||
/**
|
||||
* One of the conditions for using vtable_stack is a nothrow move constructor,
|
||||
* so this move constructor will never throw a exception.
|
||||
*/
|
||||
new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
|
||||
destroy(src);
|
||||
}
|
||||
|
||||
|
||||
static void swap(storage_union& lhs, storage_union& rhs) noexcept
|
||||
{
|
||||
storage_union tmp_storage;
|
||||
move(rhs, tmp_storage);
|
||||
move(lhs, rhs);
|
||||
move(tmp_storage, lhs);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Whether the type T must be dynamically allocated or can be stored on the stack.
|
||||
*/
|
||||
template<typename T>
|
||||
struct requires_allocation :
|
||||
std::integral_constant<bool, !(std::is_nothrow_move_constructible<T>::value // N4562 6.3/3 [any.class]
|
||||
&& sizeof(T) <= sizeof(storage_union::stack)
|
||||
&& std::alignment_of<T>::value <= std::alignment_of<storage_union::stack_storage_t>::value)>
|
||||
{ };
|
||||
|
||||
|
||||
/**
|
||||
* Returns the pointer to the vtable of the type T.
|
||||
*/
|
||||
template<typename T>
|
||||
static vtable_type* vtable_for_type()
|
||||
{
|
||||
using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
|
||||
static vtable_type table = { VTableType::type, VTableType::destroy, VTableType::copy, VTableType::move, VTableType::swap };
|
||||
return &table;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
friend const T* any_cast(const any* operand) noexcept;
|
||||
|
||||
|
||||
template<typename T>
|
||||
friend T* any_cast(any* operand) noexcept;
|
||||
|
||||
|
||||
/**
|
||||
* Same effect as is_same(this->type(), t);
|
||||
*/
|
||||
bool is_typed(const std::type_info& t) const
|
||||
{
|
||||
return is_same(this->type(), t);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if two type infos are the same.
|
||||
* If ANY_IMPL_FAST_TYPE_INFO_COMPARE is defined, checks only the address of the
|
||||
* type infos, otherwise does an actual comparision. Checking addresses is
|
||||
* only a valid approach when there's no interaction with outside sources
|
||||
* (other shared libraries and such).
|
||||
*/
|
||||
static bool is_same(const std::type_info& a, const std::type_info& b)
|
||||
{
|
||||
#ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
|
||||
return &a == &b;
|
||||
#else
|
||||
return a == b;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Casts (with no type_info checks) the storage pointer as const T*.
|
||||
*/
|
||||
template<typename T>
|
||||
const T* cast() const noexcept
|
||||
{
|
||||
return requires_allocation<typename std::decay<T>::type>::value ? reinterpret_cast<const T*>(storage.dynamic) : reinterpret_cast<const T*>(&storage.stack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Casts (with no type_info checks) the storage pointer as T*.
|
||||
*/
|
||||
template<typename T>
|
||||
T* cast() noexcept
|
||||
{
|
||||
return requires_allocation<typename std::decay<T>::type>::value ? reinterpret_cast<T*>(storage.dynamic) : reinterpret_cast<T*>(&storage.stack);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
storage_union storage; // On offset(0) so no padding for align
|
||||
|
||||
vtable_type* vtable;
|
||||
|
||||
|
||||
template<typename ValueType, typename T>
|
||||
typename std::enable_if<requires_allocation<T>::value>::type do_construct(ValueType&& value)
|
||||
{
|
||||
storage.dynamic = new T(std::forward<ValueType>(value));
|
||||
}
|
||||
|
||||
|
||||
template<typename ValueType, typename T>
|
||||
typename std::enable_if<!requires_allocation<T>::value>::type do_construct(ValueType&& value)
|
||||
{
|
||||
new (&storage.stack) T(std::forward<ValueType>(value));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Chooses between stack and dynamic allocation for the type decay_t<ValueType>,
|
||||
* assigns the correct vtable, and constructs the object on our storage.
|
||||
*/
|
||||
template<typename ValueType>
|
||||
void construct(ValueType&& value)
|
||||
{
|
||||
using T = typename std::decay<ValueType>::type;
|
||||
|
||||
this->vtable = vtable_for_type<T>();
|
||||
|
||||
do_construct<ValueType,T>(std::forward<ValueType>(value));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast_move_if_true(typename std::remove_reference<ValueType>::type* p, std::true_type)
|
||||
{
|
||||
return std::move(*p);
|
||||
}
|
||||
|
||||
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast_move_if_true(typename std::remove_reference<ValueType>::type* p, std::false_type)
|
||||
{
|
||||
return *p;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs *any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand), or throws bad_any_cast on failure.
|
||||
*/
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(const any& operand)
|
||||
{
|
||||
auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
|
||||
if(p == nullptr) {
|
||||
std::cout << "libany err-01\n";
|
||||
|
||||
throw bad_any_cast();
|
||||
}
|
||||
return *p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs *any_cast<remove_reference_t<ValueType>>(&operand), or throws bad_any_cast on failure.
|
||||
*/
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(any& operand)
|
||||
{
|
||||
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
|
||||
if(p == nullptr) throw bad_any_cast();
|
||||
return *p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If ANY_IMPL_ANYCAST_MOVEABLE is not defined, does as N4562 specifies:
|
||||
* Performs *any_cast<remove_reference_t<ValueType>>(&operand), or throws bad_any_cast on failure.
|
||||
*
|
||||
* If ANY_IMPL_ANYCAST_MOVEABLE is defined, does as LWG Defect 2509 specifies [1]:
|
||||
* If ValueType is MoveConstructible and isn't a lvalue reference, performs
|
||||
* std::move(*any_cast<remove_reference_t<ValueType>>(&operand)), otherwise
|
||||
* *any_cast<remove_reference_t<ValueType>>(&operand).
|
||||
* Throws bad_any_cast on failure.
|
||||
*
|
||||
* [1] https://cplusplus.github.io/LWG/lwg-active.html#2509
|
||||
*/
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(any&& operand)
|
||||
{
|
||||
#ifdef ANY_IMPL_ANY_CAST_MOVEABLE
|
||||
using can_move = std::integral_constant<bool, std::is_move_constructible<ValueType>::value && !std::is_lvalue_reference<ValueType>::value>;
|
||||
#else
|
||||
using can_move = std::false_type;
|
||||
#endif
|
||||
|
||||
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
|
||||
if(p == nullptr) throw bad_any_cast();
|
||||
return detail::any_cast_move_if_true<ValueType>(p, can_move());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object
|
||||
* contained by operand, otherwise nullptr.
|
||||
*/
|
||||
template<typename T>
|
||||
inline const T* any_cast(const any* operand) noexcept
|
||||
{
|
||||
if(operand == nullptr || !operand->is_typed(typeid(T)))
|
||||
return nullptr;
|
||||
else
|
||||
return operand->cast<T>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object
|
||||
* contained by operand, otherwise nullptr.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T* any_cast(any* operand) noexcept
|
||||
{
|
||||
if(operand == nullptr || !operand->is_typed(typeid(T)))
|
||||
return nullptr;
|
||||
else
|
||||
return operand->cast<T>();
|
||||
}
|
||||
|
||||
|
||||
inline void swap(any& lhs, any& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* ANY_H */
|
||||
20
v4/any.h
20
v4/any.h
@@ -8,13 +8,15 @@
|
||||
* + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4562.html#any
|
||||
* + https://cplusplus.github.io/LWG/lwg-active.html#2509
|
||||
*
|
||||
* Copyright (c) 2016 Denilson das Merc<EFBFBD>s Amorim
|
||||
* Copyright (c) 2016 Denilson das Merc?s Amorim
|
||||
* Copyright (c) 2018 Claudio Fantacci
|
||||
*
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE.md or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#ifndef ANY_H
|
||||
#define ANY_H
|
||||
|
||||
@@ -467,7 +469,10 @@ template<typename ValueType>
|
||||
inline ValueType any_cast(const any& operand)
|
||||
{
|
||||
auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
|
||||
if(p == nullptr) throw bad_any_cast();
|
||||
if(p == nullptr) {
|
||||
std::cout << "libany err-01\n";
|
||||
throw bad_any_cast();
|
||||
}
|
||||
return *p;
|
||||
}
|
||||
|
||||
@@ -479,7 +484,11 @@ template<typename ValueType>
|
||||
inline ValueType any_cast(any& operand)
|
||||
{
|
||||
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
|
||||
if(p == nullptr) throw bad_any_cast();
|
||||
if(p == nullptr) {
|
||||
std::cout << "libany err-02\n";
|
||||
throw bad_any_cast();
|
||||
}
|
||||
|
||||
return *p;
|
||||
}
|
||||
|
||||
@@ -506,7 +515,10 @@ inline ValueType any_cast(any&& operand)
|
||||
#endif
|
||||
|
||||
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
|
||||
if(p == nullptr) throw bad_any_cast();
|
||||
if(p == nullptr) {
|
||||
std::cout << "libany err-03\n";
|
||||
throw bad_any_cast();
|
||||
}
|
||||
return detail::any_cast_move_if_true<ValueType>(p, can_move());
|
||||
}
|
||||
|
||||
|
||||
1
v4/ctx.h
1
v4/ctx.h
@@ -1,6 +1,7 @@
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include "any.h"
|
||||
|
||||
#ifndef ctx_HEADER
|
||||
#define ctx_HEADER
|
||||
|
||||
@@ -9,8 +9,10 @@ std::string ctx_test_Controller_executeFunctions_set() {
|
||||
ctx_Controller<memory_Context> ctrl(c);
|
||||
// Disable automatic invocation of executeFunctions.
|
||||
ctrl.isProcessingQueue = true;
|
||||
std::cout << "01\n";
|
||||
ctrl.set("input", "123");
|
||||
std::cout << "input: '" << ctrl.context.input << "'" << std::endl;
|
||||
std::cout << "02\n";
|
||||
|
||||
auto processInput = [](memory_Context c) -> memory_Context {
|
||||
if (c.recentField == "input") {
|
||||
|
||||
@@ -1,5 +1,91 @@
|
||||
#include <utility>
|
||||
#include "any.h"
|
||||
#include "memory_Context.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
libany::any memory_Context::field(const std::string &fieldName) {
|
||||
if (fieldName == "didLaunch") {
|
||||
return didLaunch;
|
||||
} else if (fieldName == "exit") {
|
||||
return exit;
|
||||
} else if (fieldName == "hiddenItems") {
|
||||
return hiddenItems;
|
||||
} else if (fieldName == "input") {
|
||||
return input;
|
||||
} else if (fieldName == "mismatchedItems") {
|
||||
return mismatchedItems;
|
||||
} else if (fieldName == "outputGoOn") {
|
||||
return outputGoOn;
|
||||
} else if (fieldName == "outputGreeting") {
|
||||
return outputGreeting;
|
||||
} else if (fieldName == "outputHelp") {
|
||||
return outputHelp;
|
||||
} else if (fieldName == "outputMatchedItems") {
|
||||
return outputMatchedItems;
|
||||
} else if (fieldName == "outputMismatchedItems") {
|
||||
return outputMismatchedItems;
|
||||
} else if (fieldName == "outputPromptSelection") {
|
||||
return outputPromptSelection;
|
||||
} else if (fieldName == "outputVictory") {
|
||||
return outputVictory;
|
||||
} else if (fieldName == "playfieldItems") {
|
||||
return playfieldItems;
|
||||
} else if (fieldName == "playfieldSize") {
|
||||
return playfieldSize;
|
||||
} else if (fieldName == "selectedId") {
|
||||
return selectedId;
|
||||
} else if (fieldName == "selectedItems") {
|
||||
return selectedItems;
|
||||
}
|
||||
// victory
|
||||
return victory;
|
||||
}
|
||||
|
||||
void memory_Context::setField(const std::string &fieldName, libany::any value) {
|
||||
if (fieldName == "didLaunch") {
|
||||
didLaunch = libany::any_cast<bool>(value);
|
||||
} else if (fieldName == "exit") {
|
||||
exit = libany::any_cast<bool>(value);
|
||||
} else if (fieldName == "hiddenItems") {
|
||||
hiddenItems = libany::any_cast<std::vector<int> >(value);
|
||||
} else if (fieldName == "input") {
|
||||
std::cout << "memory_Context-01\n";
|
||||
try {
|
||||
input = libany::any_cast<std::string>(value);
|
||||
} catch (libany::bad_any_cast &e) {
|
||||
std::cout << "memory_Context-01 exception/type: " << e.what() << ", " << value.type().name() << std::endl;
|
||||
}
|
||||
std::cout << "memory_Context-02\n";
|
||||
} else if (fieldName == "mismatchedItems") {
|
||||
mismatchedItems = libany::any_cast<std::vector<int> >(value);
|
||||
} else if (fieldName == "outputGoOn") {
|
||||
outputGoOn = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputGreeting") {
|
||||
outputGreeting = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputHelp") {
|
||||
outputHelp = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputMatchedItems") {
|
||||
outputMatchedItems = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputMismatchedItems") {
|
||||
outputMismatchedItems = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputPromptSelection") {
|
||||
outputPromptSelection = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "outputVictory") {
|
||||
outputVictory = libany::any_cast<std::string>(value);
|
||||
} else if (fieldName == "playfieldItems") {
|
||||
playfieldItems = libany::any_cast<std::map<int, int> >(value);
|
||||
} else if (fieldName == "playfieldSize") {
|
||||
playfieldSize = libany::any_cast<int>(value);
|
||||
} else if (fieldName == "selectedId") {
|
||||
selectedId = libany::any_cast<int>(value);
|
||||
} else if (fieldName == "selectedItems") {
|
||||
selectedItems = libany::any_cast<std::vector<int> >(value);
|
||||
} else if (fieldName == "victory") {
|
||||
victory = libany::any_cast<bool>(value);
|
||||
}
|
||||
}
|
||||
|
||||
memory_Context memory_createContext() {
|
||||
return memory_Context();
|
||||
}
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
struct memory_Context {
|
||||
bool didLaunch = false;
|
||||
bool exit = false;
|
||||
std::string input = "";
|
||||
std::vector<int> hiddenItems;
|
||||
std::string input = "";
|
||||
std::vector<int> mismatchedItems;
|
||||
std::string recentField = "none";
|
||||
std::string outputGoOn = "";
|
||||
std::string outputGreeting = "";
|
||||
std::string outputHelp = "";
|
||||
@@ -22,101 +21,13 @@ struct memory_Context {
|
||||
std::string outputVictory = "";
|
||||
std::map<int, int> playfieldItems;
|
||||
int playfieldSize = 0;
|
||||
std::string recentField = "none";
|
||||
int selectedId = -1;
|
||||
std::vector<int> selectedItems;
|
||||
bool victory = false;
|
||||
|
||||
template <typename T> T field(const std::string &fieldName) {
|
||||
if (fieldName == "didLaunch") {
|
||||
return *reinterpret_cast<T*>(&didLaunch);
|
||||
} else if (fieldName == "exit") {
|
||||
return *reinterpret_cast<T*>(&exit);
|
||||
} else if (fieldName == "input") {
|
||||
return *reinterpret_cast<T*>(&input);
|
||||
} else if (fieldName == "hiddenItems") {
|
||||
return *reinterpret_cast<T*>(&hiddenItems);
|
||||
} else if (fieldName == "mismatchedItems") {
|
||||
return *reinterpret_cast<T*>(&mismatchedItems);
|
||||
} else if (fieldName == "outputGoOn") {
|
||||
return *reinterpret_cast<T*>(&outputGoOn);
|
||||
} else if (fieldName == "outputGreeting") {
|
||||
return *reinterpret_cast<T*>(&outputGreeting);
|
||||
} else if (fieldName == "outputHelp") {
|
||||
return *reinterpret_cast<T*>(&outputHelp);
|
||||
} else if (fieldName == "outputMatchedItems") {
|
||||
return *reinterpret_cast<T*>(&outputMatchedItems);
|
||||
} else if (fieldName == "outputMismatchedItems") {
|
||||
return *reinterpret_cast<T*>(&outputMismatchedItems);
|
||||
} else if (fieldName == "outputPromptSelection") {
|
||||
return *reinterpret_cast<T*>(&outputPromptSelection);
|
||||
} else if (fieldName == "outputVictory") {
|
||||
return *reinterpret_cast<T*>(&outputVictory);
|
||||
} else if (fieldName == "playfieldItems") {
|
||||
return *reinterpret_cast<T*>(&playfieldItems);
|
||||
} else if (fieldName == "playfieldSize") {
|
||||
return *reinterpret_cast<T*>(&playfieldSize);
|
||||
} else if (fieldName == "selectedId") {
|
||||
return *reinterpret_cast<T*>(&selectedId);
|
||||
} else if (fieldName == "selectedItems") {
|
||||
return *reinterpret_cast<T*>(&selectedItems);
|
||||
}
|
||||
// victory
|
||||
return *reinterpret_cast<T*>(&victory);
|
||||
}
|
||||
|
||||
void setField(const std::string &fieldName, bool value) {
|
||||
if (fieldName == "didLaunch") {
|
||||
didLaunch = value;
|
||||
} else if (fieldName == "exit") {
|
||||
exit = value;
|
||||
} else if (fieldName == "victory") {
|
||||
victory = value;
|
||||
}
|
||||
}
|
||||
|
||||
void setField(const std::string &fieldName, const std::string &value) {
|
||||
if (fieldName == "input") {
|
||||
input = value;
|
||||
} else if (fieldName == "outputGoOn") {
|
||||
outputGoOn = value;
|
||||
} else if (fieldName == "outputGreeting") {
|
||||
outputGreeting = value;
|
||||
} else if (fieldName == "outputHelp") {
|
||||
outputHelp = value;
|
||||
} else if (fieldName == "outputMatchedItems") {
|
||||
outputMatchedItems = value;
|
||||
} else if (fieldName == "outputMismatchedItems") {
|
||||
outputMismatchedItems = value;
|
||||
} else if (fieldName == "outputPromptSelection") {
|
||||
outputPromptSelection = value;
|
||||
} else if (fieldName == "outputVictory") {
|
||||
outputVictory = value;
|
||||
}
|
||||
}
|
||||
|
||||
void setField(const std::string &fieldName, const std::vector<int> &value) {
|
||||
if (fieldName == "hiddenItems") {
|
||||
hiddenItems = value;
|
||||
} else if (fieldName == "mismatchedItems") {
|
||||
mismatchedItems = value;
|
||||
} else if (fieldName == "selectedItems") {
|
||||
selectedItems = value;
|
||||
}
|
||||
}
|
||||
|
||||
void setField(const std::string &fieldName, const std::map<int, int> &value) {
|
||||
if (fieldName == "playfieldItems") {
|
||||
playfieldItems = value;
|
||||
}
|
||||
}
|
||||
|
||||
void setField(const std::string &fieldName, int value) {
|
||||
if (fieldName == "playfieldSize") {
|
||||
playfieldSize = value;
|
||||
} else if (fieldName == "selectedId") {
|
||||
selectedId = value;
|
||||
}
|
||||
}
|
||||
libany::any field(const std::string &fieldName);
|
||||
void setField(const std::string &fieldName, libany::any value);
|
||||
};
|
||||
|
||||
memory_Context memory_createContext();
|
||||
|
||||
Reference in New Issue
Block a user