Add files
This commit is contained in:
130
core/include/bertini2/detail/configured.hpp
Normal file
130
core/include/bertini2/detail/configured.hpp
Normal file
@@ -0,0 +1,130 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//configured.hpp 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.
|
||||
//
|
||||
//configured.hpp 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 configured.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2016 - 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
// individual authors of this file include:
|
||||
// silviana amethyst, university of wisconsin-eau claire
|
||||
//
|
||||
// detail/configured.hpp
|
||||
|
||||
|
||||
/**
|
||||
\file detail/configured.hpp
|
||||
|
||||
\brief Contains the detail/configured helper type, for templated getting/setting/storage of config structs
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bertini2/detail/is_template_parameter.hpp"
|
||||
|
||||
namespace bertini {
|
||||
|
||||
namespace detail{
|
||||
|
||||
|
||||
/**
|
||||
This templated struct allows one to provide a variable typelist of config structs (or anything else for that matter), and provides a way to get and set these configs by looking up the structs by type.
|
||||
|
||||
I will add lookup by index if it is needed. If you need to look up by index, try type first. If your types are non-unique, consider making a struct to hold the things you are storing.
|
||||
|
||||
|
||||
## On nested configs. If two or more things in your inheritance tree require Configured,
|
||||
consider the following code, which can help determine whether to Get or Set from here, or to pass
|
||||
down the tree to a base class.
|
||||
|
||||
\code
|
||||
template <typename T>
|
||||
const
|
||||
typename std::enable_if<detail::IsTemplateParameter<T, config::Cauchy<typename TrackerTraits<TrackerType>::BaseRealType>>::value, T>::type
|
||||
& Get() const
|
||||
{
|
||||
return Config::template Get<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const
|
||||
typename std::enable_if<not detail::IsTemplateParameter<T, config::Cauchy<typename TrackerTraits<TrackerType>::BaseRealType>>::value, T>::type
|
||||
& Get() const
|
||||
{
|
||||
return EndgameBase<TrackerType, FinalEGT, UsedNumTs...>::template Get<T>();
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<detail::IsTemplateParameter<T, config::Cauchy<typename TrackerTraits<TrackerType>::BaseRealType>>::value, void>::type
|
||||
Set(T const& t)
|
||||
{
|
||||
Config::template Set(t);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<not detail::IsTemplateParameter<T, config::Cauchy<typename TrackerTraits<TrackerType>::BaseRealType>>::value, void>::type
|
||||
Set(T const& t)
|
||||
{
|
||||
EndgameBase<TrackerType, FinalEGT, UsedNumTs...>::template Set(t);
|
||||
}
|
||||
\endcode
|
||||
|
||||
*/
|
||||
template<typename ...Ts>
|
||||
struct Configured
|
||||
{
|
||||
std::tuple<Ts...> configuration_;
|
||||
|
||||
template<typename ... T>
|
||||
Configured(T const& ...t) : configuration_(t...)
|
||||
{}
|
||||
|
||||
|
||||
template<typename T, typename = typename std::enable_if<IsTemplateParameter<T,Ts...>::value>::type>
|
||||
const T& Get() const
|
||||
{
|
||||
return std::get<T>(configuration_);
|
||||
}
|
||||
|
||||
template<typename T, typename = typename std::enable_if<IsTemplateParameter<T,Ts...>::value>::type>
|
||||
void Set(T const& t)
|
||||
{
|
||||
std::get<T>(configuration_) = t;
|
||||
}
|
||||
|
||||
using UsedConfigs = TypeList<Ts...>;
|
||||
|
||||
}; // Configured
|
||||
|
||||
template<typename ...Ts>
|
||||
struct Configured<TypeList<Ts...>> : public Configured<Ts...>
|
||||
{
|
||||
template<typename ... T>
|
||||
Configured(T const& ...t) : Configured<Ts...>(t...)
|
||||
{}
|
||||
|
||||
Configured() : Configured<Ts...>() {}
|
||||
|
||||
};
|
||||
|
||||
#define FORWARD_GET_CONFIGURED \
|
||||
template <typename T> \
|
||||
const T& Get() const \
|
||||
{ return Config::template Get<T>();}
|
||||
|
||||
} // namespace detail
|
||||
}
|
||||
141
core/include/bertini2/detail/enable_permuted_arguments.hpp
Normal file
141
core/include/bertini2/detail/enable_permuted_arguments.hpp
Normal file
@@ -0,0 +1,141 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//enable_permuted_arguments.hpp 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.
|
||||
//
|
||||
//enable_permuted_arguments.hpp 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 enable_permuted_arguments.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
// individual authors of this file include:
|
||||
// silviana amethyst, university of wisconsin eau claire
|
||||
// additionally, this file contains code
|
||||
// based on and refined from SO post
|
||||
// https://stackoverflow.com/questions/19329297/constructor-permutations-for-passing-parameters-in-arbitrary-order
|
||||
// by user Daniel Frey.
|
||||
|
||||
/**
|
||||
\file enable_permuted_arguments.hpp
|
||||
|
||||
Contains helper templates, based on and refined from SO post
|
||||
https://stackoverflow.com/questions/19329297/constructor-permutations-for-passing-parameters-in-arbitrary-order
|
||||
by user Daniel Frey.
|
||||
*/
|
||||
|
||||
#ifndef BERTINI_ENABLE_PERMUTED_ARGUMENTS
|
||||
#define BERTINI_ENABLE_PERMUTED_ARGUMENTS
|
||||
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
|
||||
|
||||
namespace bertini {
|
||||
|
||||
|
||||
namespace detail {
|
||||
// find the index of a type in a list of types,
|
||||
// return sizeof...(Remaining) if T is not found
|
||||
template< typename T, typename... Remaining >
|
||||
struct IndexByType : std::integral_constant< std::size_t, 0 >
|
||||
{};
|
||||
|
||||
// template specialization, enforcing the equality of the number of variadic arguments, and the corresponding index.
|
||||
// if two types are the same, this template will be preferred since it's a closer match, and the static_assert will fail, preventing compilation.
|
||||
template< typename T, typename... RemainingT >
|
||||
struct IndexByType< T, T, RemainingT... > : std::integral_constant< std::size_t, 0 >
|
||||
{
|
||||
static_assert( IndexByType< T, RemainingT... >::value == sizeof...( RemainingT ), "No duplicates are allowed when enabling permuted arguments" );
|
||||
};
|
||||
|
||||
// template specialization on two types. looks for the index of T in the latter arguments. If T1==T2, this template will not be used, but instead the above will.
|
||||
template< typename T1, typename T2, typename... RemainingT >
|
||||
struct IndexByType< T1, T2, RemainingT... > : std::integral_constant< std::size_t, IndexByType< T1, RemainingT... >::value + 1 >
|
||||
{};
|
||||
|
||||
// a free function which gets a type from a tuple with no duplicates. Remember, duplicates are not allowed.
|
||||
template< std::size_t I, std::size_t J,
|
||||
typename T, typename... PresentT, typename... GivenT >
|
||||
auto GetByIndex( const std::tuple< PresentT... >&,
|
||||
const std::tuple< GivenT... >& absent_args )
|
||||
-> typename std::enable_if< I == sizeof...( PresentT ), const T& >::type
|
||||
{
|
||||
return std::get< J >( absent_args );
|
||||
}
|
||||
|
||||
// the other half of the get by index function
|
||||
template< std::size_t I, std::size_t J,
|
||||
typename T, typename... PresentT, typename... GivenT >
|
||||
auto GetByIndex(const std::tuple< PresentT... >& present_args,
|
||||
const std::tuple< GivenT... >& ) // these arguments will have to be default constructed
|
||||
-> typename std::enable_if< I != sizeof...( PresentT ), const T& >::type /* remember, `I != sizeof...( PresentT )` means it found T in PresentT */
|
||||
{
|
||||
return std::get< I >( present_args );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// helper to validate that all Us are in Ts...
|
||||
template< bool > struct AreValidArguments;
|
||||
|
||||
// the false one is never instantiated, so the 'false' template parameter will fail, deliberately
|
||||
template<> struct AreValidArguments< true > : std::true_type
|
||||
{};
|
||||
|
||||
// a proxy function which to ensure that the types are distinct, and that we can indeed get the index by type.
|
||||
template< std::size_t... >
|
||||
void ValidateTypes()
|
||||
{}
|
||||
|
||||
|
||||
|
||||
// default construct the objects not present in the arguments, but required by the unpermute function
|
||||
template< typename T >
|
||||
struct DefaultConstruct
|
||||
{ static const T value; };
|
||||
|
||||
template< typename T >
|
||||
const T DefaultConstruct< T >::value
|
||||
{};
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// helper template which reorders parameters
|
||||
template< typename... UnpermutedT, // these must be declared when using the function
|
||||
typename... PermutedPresentT > // these are inferred, cannot be declared
|
||||
std::tuple< const UnpermutedT&... > Unpermute( const PermutedPresentT&... present_permuted_args )
|
||||
{
|
||||
using namespace detail;
|
||||
auto present_args = std::tie( present_permuted_args... );
|
||||
auto absent_args = std::tie( DefaultConstruct< UnpermutedT >::value... );
|
||||
|
||||
//next we validate that the input arguments are valid for unpermuting. must have all distinct types.
|
||||
ValidateTypes< AreValidArguments< IndexByType< const PermutedPresentT&,
|
||||
const UnpermutedT&... >::value != sizeof...( UnpermutedT )
|
||||
>::value...
|
||||
>(); // this will fail if AreValidArguments are not valid ('true')
|
||||
|
||||
// finally, we return a tie of the unpermuted types, default constructed if necessary
|
||||
return std::tie( GetByIndex< IndexByType< const UnpermutedT&, const PermutedPresentT&... >::value,
|
||||
IndexByType< const UnpermutedT&, const UnpermutedT&... >::value, UnpermutedT >
|
||||
( present_args, absent_args )... );
|
||||
}
|
||||
|
||||
|
||||
} // re: namespace bertini
|
||||
|
||||
#endif
|
||||
165
core/include/bertini2/detail/events.hpp
Normal file
165
core/include/bertini2/detail/events.hpp
Normal file
@@ -0,0 +1,165 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//events.hpp 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.
|
||||
//
|
||||
//events.hpp 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 events.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
// individual authors of this file include:
|
||||
// silviana amethyst, university of wisconsin-eau claire
|
||||
//
|
||||
|
||||
// detail/events.hpp
|
||||
|
||||
|
||||
/**
|
||||
\file detail/events.hpp
|
||||
|
||||
\brief Contains the detail/events base types
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BERTINI_DETAIL_EVENTS_HPP
|
||||
#define BERTINI_DETAIL_EVENTS_HPP
|
||||
#include <boost/type_index.hpp>
|
||||
namespace bertini {
|
||||
|
||||
/**
|
||||
\brief Strawman Event type, enabling polymorphism.
|
||||
|
||||
This class is abstract, and should never actually be created.
|
||||
*/
|
||||
class AnyEvent
|
||||
{ BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
public:
|
||||
virtual ~AnyEvent() = default;
|
||||
};
|
||||
|
||||
template<class ObsT, bool IsConst = true>
|
||||
class Event;
|
||||
|
||||
/**
|
||||
\brief For emission of events from observables.
|
||||
|
||||
An observable object probably wants to emit events to notify observers that things are happening. The observers filter the events, at this time by dynamic casting (slow, I know, but it works for now. Premature optimization, etc.) A better method than dynamic casting would be to filter based on a union of bits or something. If you, the reader, want to help make this better, please contact a developer!
|
||||
|
||||
Say I am an observable object, and I want to emit an event. Events attach the type of object emitting them, and in fact (a refence to) the emitter itself. So if my type is `T`, I would do something like `NotifyObservers(Event<T>(*this))`. Then an Observer can filter based on a heirarchy of event types, etc.
|
||||
|
||||
\tparam ObsT The Observed type. When emitting an event, you pass in the type of object emitting the event, and the object itself. Then the observer can `Get` the emitting object, and do (const) stuff to it.
|
||||
|
||||
\see Observable, Observable::NotifyObservers, ADD_BERTINI_EVENT_TYPE, AMPPathAccumulator, AnyEvent
|
||||
*/
|
||||
template<class ObsT>
|
||||
class Event<ObsT, true> : public AnyEvent
|
||||
{ BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
public:
|
||||
|
||||
/**
|
||||
\brief Constructor for an event.
|
||||
|
||||
\param obs The observable emitting the event to observers. Passed by const reference, this permits arbitrary `const` function calls by the observer.
|
||||
*/
|
||||
Event(ObsT const& obs) : current_observable_(obs)
|
||||
{}
|
||||
|
||||
virtual ~Event() = default;
|
||||
|
||||
/**
|
||||
\brief Get the emitting object, by `const` reference.
|
||||
|
||||
\return The observable who emitted the event. This permits calls of arbitrary const functions, particularly getters.
|
||||
|
||||
\see AMPPathAccumulator for simple example of filtering using `dynamic_cast`s
|
||||
*/
|
||||
ObsT const& Get() const
|
||||
{return current_observable_;}
|
||||
|
||||
Event() = delete;
|
||||
|
||||
using HeldT = const ObsT&;
|
||||
protected:
|
||||
const ObsT& current_observable_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\brief For emission of events from observables.
|
||||
|
||||
An observable object probably wants to emit events to notify observers that things are happening. The observers filter the events, at this time by dynamic casting (slow, I know, but it works for now. Premature optimization, etc.) A better method than dynamic casting would be to filter based on a union of bits or something. If you, the reader, want to help make this better, please contact a developer!
|
||||
|
||||
Say I am an observable object, and I want to emit an event. Events attach the type of object emitting them, and in fact (a refence to) the emitter itself. So if my type is `T`, I would do something like `NotifyObservers(Event<T>(*this))`. Then an Observer can filter based on a heirarchy of event types, etc.
|
||||
|
||||
\tparam ObsT The Observed type. When emitting an event, you pass in the type of object emitting the event, and the object itself. Then the observer can `Get` the emitting object, and do (const) stuff to it.
|
||||
|
||||
\see Observable, Observable::NotifyObservers, ADD_BERTINI_EVENT_TYPE, AMPPathAccumulator, AnyEvent
|
||||
*/
|
||||
template<class ObsT>
|
||||
class Event<ObsT,false> : public AnyEvent
|
||||
{ BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
public:
|
||||
|
||||
/**
|
||||
\brief Constructor for an event.
|
||||
|
||||
\param obs The observable emitting the event to observers. Passed by const reference, this permits arbitrary `const` function calls by the observer.
|
||||
*/
|
||||
Event(ObsT & obs) : current_observable_(obs)
|
||||
{}
|
||||
|
||||
virtual ~Event() = default;
|
||||
|
||||
/**
|
||||
\brief Get the emitting object, by `const` reference.
|
||||
|
||||
\return The observable who emitted the event. This permits calls of arbitrary const functions, particularly getters.
|
||||
|
||||
\see AMPPathAccumulator for simple example of filtering using `dynamic_cast`s
|
||||
*/
|
||||
ObsT & Get()
|
||||
{return current_observable_;}
|
||||
|
||||
Event() = delete;
|
||||
|
||||
using HeldT = ObsT&;
|
||||
protected:
|
||||
ObsT& current_observable_;
|
||||
};
|
||||
|
||||
template<typename ObsT>
|
||||
using ConstEvent = Event<ObsT,true>;
|
||||
|
||||
template<typename ObsT>
|
||||
using MutableEvent = Event<ObsT,false>;
|
||||
|
||||
/**
|
||||
\brief Defines a new event type in a hierarchy
|
||||
|
||||
\param event_name The name of the new Event type you are making.
|
||||
\param event_parenttype The name of the parent Event type in the heirarchy.
|
||||
*/
|
||||
#define ADD_BERTINI_EVENT_TYPE(event_name,event_parenttype) template<class ObservedT> \
|
||||
class event_name : public event_parenttype<ObservedT> \
|
||||
{ BOOST_TYPE_INDEX_REGISTER_CLASS \
|
||||
public: \
|
||||
using HeldT = typename event_parenttype<ObservedT>::HeldT; \
|
||||
event_name(HeldT obs) : event_parenttype<ObservedT>(obs){} \
|
||||
virtual ~event_name() = default; \
|
||||
event_name() = delete; }
|
||||
|
||||
} //re: namespace bertini
|
||||
|
||||
#endif
|
||||
72
core/include/bertini2/detail/is_template_parameter.hpp
Normal file
72
core/include/bertini2/detail/is_template_parameter.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//is_template_parameter.hpp 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.
|
||||
//
|
||||
//is_template_parameter.hpp 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 is_template_parameter.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
// individual authors of this file include:
|
||||
// silviana amethyst, university of wisconsin-eau claire
|
||||
//
|
||||
|
||||
// detail/is_template_parameter.hpp
|
||||
|
||||
|
||||
/**
|
||||
\file detail/is_template_parameter.hpp
|
||||
|
||||
\brief Contains the detail/is_template_parameter helper, for checking whether a type is a template parameter in a variable template
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "bertini2/detail/typelist.hpp"
|
||||
|
||||
namespace bertini {
|
||||
|
||||
namespace detail{
|
||||
|
||||
/**
|
||||
Base template, which says 'no', it's not in the pack.
|
||||
*/
|
||||
template <typename...>
|
||||
struct IsTemplateParameter {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
/**
|
||||
Specialized template, which says 'yes', if it is in the pack, by recursively expanding the pack.
|
||||
*/
|
||||
template <typename F, typename S, typename... T>
|
||||
struct IsTemplateParameter<F, S, T...> {
|
||||
static constexpr bool value =
|
||||
std::is_same<F, S>::value || IsTemplateParameter<F, T...>::value;
|
||||
// either it is the same as the first one in the pack, or we need to expand to the right in the pack.
|
||||
};
|
||||
|
||||
|
||||
template < typename T, typename ...Ts>
|
||||
struct IsTemplateParameter<T, TypeList<Ts...>>
|
||||
{
|
||||
static constexpr bool value = IsTemplateParameter<T, Ts...>::value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
}
|
||||
115
core/include/bertini2/detail/observable.hpp
Normal file
115
core/include/bertini2/detail/observable.hpp
Normal file
@@ -0,0 +1,115 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//bertini2/detail/observable.hpp 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.
|
||||
//
|
||||
//bertini2/detail/observable.hpp 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 bertini2/detail/observable.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
// individual authors of this file include:
|
||||
// silviana amethyst, university of wisconsin-eau claire
|
||||
//
|
||||
|
||||
/**
|
||||
\file bertini2/detail/observable.hpp
|
||||
|
||||
\brief Contains the observable base types
|
||||
*/
|
||||
|
||||
#ifndef BERTINI_DETAIL_OBSERVABLE_HPP
|
||||
#define BERTINI_DETAIL_OBSERVABLE_HPP
|
||||
|
||||
#include "bertini2/detail/observer.hpp"
|
||||
#include "bertini2/detail/events.hpp"
|
||||
|
||||
namespace bertini{
|
||||
|
||||
/**
|
||||
\brief An abstract observable type, maintaining a list of observers, who can be notified in case of Events.
|
||||
|
||||
Some known observable types are Tracker and Endgame.
|
||||
*/
|
||||
class Observable
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~Observable() = default;
|
||||
|
||||
|
||||
/**
|
||||
\brief Add an observer, to observe this observable.
|
||||
*/
|
||||
void AddObserver(AnyObserver& new_observer) const
|
||||
{
|
||||
if (find_if(begin(current_watchers_), end(current_watchers_), [&](const auto& held_obs)
|
||||
{ return &held_obs.get() == &new_observer; })==end(current_watchers_))
|
||||
|
||||
current_watchers_.push_back(std::ref(new_observer));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Remove an observer from this observable.
|
||||
*/
|
||||
void RemoveObserver(AnyObserver& observer) const
|
||||
{
|
||||
|
||||
auto new_end = std::remove_if(current_watchers_.begin(), current_watchers_.end(),
|
||||
[&](const auto& held_obs)
|
||||
{ return &held_obs.get() == &observer; });
|
||||
|
||||
current_watchers_.erase(new_end, current_watchers_.end());
|
||||
|
||||
|
||||
// current_watchers_.erase(std::remove(current_watchers_.begin(), current_watchers_.end(), std::ref(observer)), current_watchers_.end());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
\brief Sends an Event (more particularly, AnyEvent) to all watching observers of this object.
|
||||
|
||||
This function could potentially be improved by filtering on the observer's desired event types, if known at compile time. This could potentially be a performance bottleneck (hopefully not!) since filtering can use `dynamic_cast`ing. One hopes this cost is overwhelmed by things like linear algebra and system evaluation.
|
||||
|
||||
\param e The event to emit. Its type should be derived from AnyEvent.
|
||||
*/
|
||||
void NotifyObservers(AnyEvent const& e) const
|
||||
{
|
||||
|
||||
for (auto& obs : current_watchers_)
|
||||
obs.get().Observe(e);
|
||||
|
||||
}
|
||||
|
||||
void NotifyObservers(AnyEvent & e) const
|
||||
{
|
||||
|
||||
for (auto& obs : current_watchers_)
|
||||
obs.get().Observe(e);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
using ObserverContainer = std::vector<std::reference_wrapper<AnyObserver>>;
|
||||
|
||||
mutable ObserverContainer current_watchers_;
|
||||
};
|
||||
|
||||
} // namespace bertini
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
123
core/include/bertini2/detail/observer.hpp
Normal file
123
core/include/bertini2/detail/observer.hpp
Normal file
@@ -0,0 +1,123 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//bertini2/detail/observer.hpp 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.
|
||||
//
|
||||
//bertini2/detail/observer.hpp 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 bertini2/detail/observer.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
// individual authors of this file include:
|
||||
// silviana amethyst, university of wisconsin-eau claire
|
||||
//
|
||||
|
||||
/**
|
||||
\file bertini2/detail/observer.hpp
|
||||
|
||||
\brief Contains the observer base types.
|
||||
*/
|
||||
|
||||
#ifndef BERTINI_DETAIL_OBSERVER_HPP
|
||||
#define BERTINI_DETAIL_OBSERVER_HPP
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/fusion/adapted/std_tuple.hpp>
|
||||
|
||||
#include <boost/fusion/algorithm/iteration/for_each.hpp>
|
||||
#include <boost/fusion/include/for_each.hpp>
|
||||
|
||||
#include "bertini2/detail/events.hpp"
|
||||
|
||||
namespace bertini{
|
||||
|
||||
|
||||
/**
|
||||
\brief Strawman base class for Observer objects.
|
||||
|
||||
\see Observer
|
||||
*/
|
||||
class AnyObserver
|
||||
{ BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
public:
|
||||
virtual ~AnyObserver() = default;
|
||||
|
||||
/**
|
||||
\brief Observe the observable object being observed. This is probably in response to NotifyObservers.
|
||||
|
||||
This virtual function must be overridden by actual observers, defining how they observe the observable they are observing, probably filtering events and doing something specific for different ones.
|
||||
|
||||
\param e The event which was emitted by the observed object.
|
||||
*/
|
||||
virtual void Observe(AnyEvent const& e) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\brief Actual observer type, which you should derive from to extract custom information from observable types.
|
||||
|
||||
\tparam ObservedT The type of object the observer observes.
|
||||
\tparam RetT The type of object the observer returns when it visits.
|
||||
|
||||
\see PrecisionAccumulator, GoryDetailLogger, MultiObserver
|
||||
*/
|
||||
template<class ObservedT>
|
||||
class Observer : public AnyObserver
|
||||
{ BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
public:
|
||||
virtual ~Observer() = default;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief A class which can glob together observer types into a new, single observer type.
|
||||
|
||||
If there are pre-existing observers for the object you wish to observe, rather than making one of each, and attaching each to the observable, you can make many things one.
|
||||
|
||||
https://frinkiac.com/?q=many%20guns%20into%20five
|
||||
|
||||
\tparam ObservedT The type of thing the observer types you are gluing together observe. They must all observe the same type of object.
|
||||
\tparam ObserverTypes The already-existing observer types you are gluing together. You can put as many of them together as you want!
|
||||
*/
|
||||
template<class ObservedT, template<class> class... ObserverTypes>
|
||||
class MultiObserver : public Observer<ObservedT>
|
||||
{ BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
public:
|
||||
|
||||
/**
|
||||
\brief Observe override which calls the overrides for the types you glued together.
|
||||
|
||||
\param e The emitted event which caused observation.
|
||||
*/
|
||||
void Observe(AnyEvent const& e) override
|
||||
{
|
||||
using namespace boost::fusion;
|
||||
auto f = [&e](auto &obs) { obs.Observe(e); };
|
||||
for_each(observers_, f);
|
||||
}
|
||||
|
||||
std::tuple<ObserverTypes<ObservedT>...> observers_;
|
||||
virtual ~MultiObserver() = default;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
62
core/include/bertini2/detail/singleton.hpp
Normal file
62
core/include/bertini2/detail/singleton.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//bertini2/detail/singleton.hpp 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.
|
||||
//
|
||||
//bertini2/detail/singleton.hpp 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 bertini2/detail/singleton.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
|
||||
/**
|
||||
\file bertini2/detail/singleton.hpp
|
||||
|
||||
\brief Provides types and utilities for dealing with global defaults for the detail routines
|
||||
*/
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace bertini{
|
||||
|
||||
namespace detail{
|
||||
|
||||
|
||||
/**
|
||||
\brief A virtual singleton base class which can be used in a heirarchy to require a class to be singleton.
|
||||
|
||||
\note
|
||||
This class is virtual, so make sure you mark destructors as virtual.
|
||||
*/
|
||||
struct Singleton {
|
||||
|
||||
|
||||
virtual ~Singleton() = default;
|
||||
private:
|
||||
// mark both the default and copy constructor as private
|
||||
Singleton(){}
|
||||
Singleton(Singleton const&){}
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace bertini
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
98
core/include/bertini2/detail/typelist.hpp
Normal file
98
core/include/bertini2/detail/typelist.hpp
Normal file
@@ -0,0 +1,98 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//typelist.hpp 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.
|
||||
//
|
||||
//typelist.hpp 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 typelist.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
// individual authors of this file include:
|
||||
// silviana amethyst, university of wisconsin-eau claire
|
||||
|
||||
|
||||
/**
|
||||
\file detail/typelist.hpp
|
||||
|
||||
\brief Contains the detail/typelist helper type, for templated getting/setting/storage of config structs
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "bertini2/detail/enable_permuted_arguments.hpp"
|
||||
#include "bertini2/eigen_extensions.hpp"
|
||||
|
||||
namespace bertini {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
\brief A basic typelist, in the style of Modern C++ Design, but using variadic templates
|
||||
|
||||
To construct one, feed the types you want into the template arguments of the TypeList
|
||||
*/
|
||||
template <typename... Ts>
|
||||
struct TypeList {
|
||||
using ToTuple = std::tuple<Ts...>;
|
||||
using ToTupleOfVec = std::tuple<Vec<Ts>...>;
|
||||
using ToTupleOfReal = std::tuple<typename Eigen::NumTraits<Ts>::Real...>;
|
||||
|
||||
template <template<typename> class ContT>
|
||||
using ToTupleOfCont = std::tuple<ContT<Ts>...>;
|
||||
|
||||
|
||||
template<typename ...Rs>
|
||||
static
|
||||
std::tuple<Ts...> Unpermute(const Rs& ...rs)
|
||||
{
|
||||
return bertini::Unpermute<Ts...>(rs...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\brief Concatenate two typelists
|
||||
|
||||
Get resulting TypeList via something like `ListCat< TypeList<int>,TypeList<double> >::type`
|
||||
*/
|
||||
template <typename ...Ts>
|
||||
struct ListCat {};
|
||||
|
||||
|
||||
/**
|
||||
\brief A specialization of ListCat for joining two lists
|
||||
*/
|
||||
template <typename ...Ts, typename ... Rs>
|
||||
struct ListCat <TypeList<Ts...>, TypeList<Rs...>>
|
||||
{
|
||||
using type = TypeList<Ts..., Rs...>;
|
||||
};
|
||||
|
||||
/**
|
||||
\brief A specialization of ListCat for joining 3+ lists
|
||||
|
||||
This specialization works via recursion
|
||||
*/
|
||||
template <typename ...Ps, typename ... Qs, typename ... Rs>
|
||||
struct ListCat <TypeList<Ps...>, TypeList<Qs...>, TypeList<Rs...>>
|
||||
{
|
||||
using type = TypeList<Ps..., Qs..., Rs...>;
|
||||
};
|
||||
|
||||
}} // close namespaces
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
129
core/include/bertini2/detail/visitable.hpp
Normal file
129
core/include/bertini2/detail/visitable.hpp
Normal file
@@ -0,0 +1,129 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//visitable.hpp 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.
|
||||
//
|
||||
//visitable.hpp 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 visitable.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
// individual authors of this file include:
|
||||
// silviana amethyst, university of wisconsin-eau claire
|
||||
//
|
||||
|
||||
/**
|
||||
\file visitable.hpp
|
||||
|
||||
\brief Contains the visitable base types
|
||||
*/
|
||||
|
||||
#ifndef BERTINI_DETAIL_VISITABLE_HPP
|
||||
#define BERTINI_DETAIL_VISITABLE_HPP
|
||||
|
||||
#include "bertini2/detail/visitor.hpp"
|
||||
#include "bertini2/detail/events.hpp"
|
||||
|
||||
namespace bertini{
|
||||
|
||||
namespace policy{
|
||||
|
||||
/**
|
||||
\brief A policy for what to do when a visited type is encoutered by a visitor it doesn't know.
|
||||
|
||||
Defines the default behaviour when an unknown visitor is encountered during visitation.
|
||||
|
||||
Assumes the return type is default constructible.
|
||||
*/
|
||||
template<class VisitedT, typename RetT>
|
||||
struct DefaultConstruct
|
||||
{
|
||||
static RetT OnUnknownVisitor(VisitedT&a, VisitorBase&) // VisitorBase is inherited from using CRTP -- it's not a template parameter to this function, so its typeid name is useless.
|
||||
{
|
||||
std::cout << "unknown visitor: " << a << " of type " << typeid(VisitedT).name() << ". Make sure you've added it in all three places! two in the class definition (type inheritance listing as visiting, and virtual function declaration), and one in cpp source (function definition)." << std::endl;
|
||||
return VisitedT();
|
||||
}
|
||||
};
|
||||
|
||||
template<class VisitedT, typename RetT>
|
||||
struct RaiseExceptionWithTypeNamesInMessage
|
||||
{
|
||||
static RetT OnUnknownVisitor(VisitedT&a, VisitorBase&)
|
||||
{
|
||||
std::stringstream err_msg;
|
||||
err_msg << "unknown visitor: " << a << " of type " << typeid(VisitedT).name() << ". Make sure you've added it in all three places! two in the class definition (type inheritance listing as visiting, and virtual function declaration), and one in cpp source (function definition)." << std::endl;
|
||||
throw std::runtime_error(err_msg.str());
|
||||
}
|
||||
};
|
||||
/**
|
||||
The default policy for what to do when a visitable is visited by an unknown visitor.
|
||||
*/
|
||||
template<class VisitedT, typename RetT>
|
||||
using DefaultCatchAll = RaiseExceptionWithTypeNamesInMessage<VisitedT, RetT>;
|
||||
} // namespace policy
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief The base class for visitable types.
|
||||
|
||||
Implemented based on Alexandrescu, 2001, and Hythem Sidky's SAPHRON package, with his permission.
|
||||
|
||||
\see BERTINI_DEFAULT_VISITABLE
|
||||
*/
|
||||
template< typename RetT = void, template<class,class> class CatchAll = policy::DefaultCatchAll>
|
||||
class VisitableBase
|
||||
{
|
||||
public:
|
||||
typedef RetT VisitReturnType;
|
||||
virtual ~VisitableBase() = default;
|
||||
virtual VisitReturnType Accept(VisitorBase&) = 0; // the implementation will either be provided by a macro, or by hand, for each class which is visitable.
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
\brief Abstract method for how to accept a visitor.
|
||||
|
||||
This function simply Forwards to the Visit method of the visitor, if the visitor's type is known. If known, invokes the behaviour defined by the CatchAll template parameter.
|
||||
|
||||
\tparam T The type of the visited object. Should be inferred by the compiler.
|
||||
|
||||
\param visited The visited visitable object.
|
||||
\param guest The visiting object.
|
||||
*/
|
||||
template<typename T>
|
||||
static
|
||||
VisitReturnType AcceptBase(T& visited, VisitorBase& guest)
|
||||
{
|
||||
if (auto p = dynamic_cast<Visitor<T>*>(&guest))
|
||||
return p->Visit(visited);
|
||||
else
|
||||
return CatchAll<T,RetT>::OnUnknownVisitor(visited, guest);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\brief macro for classes which want default Accept implementation, having nothing fancy to do when accepting.
|
||||
*/
|
||||
#define BERTINI_DEFAULT_VISITABLE() \
|
||||
virtual VisitReturnType Accept(VisitorBase& guest) override \
|
||||
{ return AcceptBase(*this, guest); }
|
||||
|
||||
} // namespace bertini
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
73
core/include/bertini2/detail/visitor.hpp
Normal file
73
core/include/bertini2/detail/visitor.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
//This file is part of Bertini 2.
|
||||
//
|
||||
//visitor.hpp 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.
|
||||
//
|
||||
//visitor.hpp 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 visitor.hpp. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
|
||||
//
|
||||
// See <http://www.gnu.org/licenses/> for a copy of the license,
|
||||
// as well as COPYING. Bertini2 is provided with permitted
|
||||
// additional terms in the b2/licenses/ directory.
|
||||
|
||||
// individual authors of this file include:
|
||||
// silviana amethyst, university of wisconsin-eau claire
|
||||
//
|
||||
|
||||
/**
|
||||
\file visitor.hpp
|
||||
|
||||
\brief Contains the visitor base types.
|
||||
*/
|
||||
|
||||
#ifndef BERTINI_DETAIL_VISITOR_HPP
|
||||
#define BERTINI_DETAIL_VISITOR_HPP
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace bertini{
|
||||
|
||||
/**
|
||||
\brief A strawman class for implementing the visitor pattern.
|
||||
|
||||
Deliberately empty, the non-base visitors must derive from it.
|
||||
|
||||
\see Visitor, Observer, AnyObserver, MultiObserver
|
||||
*/
|
||||
class VisitorBase
|
||||
{ BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
public:
|
||||
virtual ~VisitorBase() = default;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\brief The first non-trivial visitor class.
|
||||
|
||||
Derive from this when creating new visitor types.
|
||||
|
||||
\tparam VisitedT The type of object the visitor visits.
|
||||
\tparam RetT The type of object to be returned when visiting. Default is `void`.
|
||||
*/
|
||||
template<class VisitedT, typename RetT = void>
|
||||
class Visitor
|
||||
{ BOOST_TYPE_INDEX_REGISTER_CLASS
|
||||
public:
|
||||
typedef RetT ReturnType;
|
||||
virtual ReturnType Visit(VisitedT const &) = 0;
|
||||
virtual ~Visitor() = default;
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user