|
|
|
#pragma once
|
|
|
|
#include "ParseArgs.h"
|
|
|
|
#include <concepts>
|
|
|
|
|
|
|
|
class BaseParameters;
|
|
|
|
|
|
|
|
using michlib::real;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept InfoSupported = requires(T t) {
|
|
|
|
{
|
|
|
|
t.Info()
|
|
|
|
} -> std::convertible_to<MString>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept HasDefVars = requires(T t) {
|
|
|
|
{
|
|
|
|
t.DefaultVars()
|
|
|
|
} -> std::convertible_to<MString>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ParametersRequiredRegion = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args, const struct Region& r) {
|
|
|
|
{
|
|
|
|
t.Parameters(pars, args, r).first
|
|
|
|
} -> std::convertible_to<const BaseParameters*>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ParametersNotRequiredRegion = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args) {
|
|
|
|
{
|
|
|
|
t.Parameters(pars, args).first
|
|
|
|
} -> std::convertible_to<const BaseParameters*>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ParametersSupported = ParametersRequiredRegion<T> || ParametersNotRequiredRegion<T>;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ReadPSupported = requires(T t, const MString& vname, std::map<MString, typename T::Data>& cache, const BaseParameters* ip, size_t i) {
|
|
|
|
{
|
|
|
|
t.Read(vname, cache, ip, i)
|
|
|
|
} -> std::same_as<bool>;
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
concept ReadSupported = requires(T t, const MString& vname, std::map<MString, typename T::Data>& cache, size_t i) {
|
|
|
|
{
|
|
|
|
t.Read(vname, cache, i)
|
|
|
|
} -> std::same_as<bool>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept IsUVData = requires(T t) {
|
|
|
|
{
|
|
|
|
t.U(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
{
|
|
|
|
t.V(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
{
|
|
|
|
t.U2(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace internal
|
|
|
|
{
|
|
|
|
template<class T>
|
|
|
|
concept HaveXYStep = requires(T t) {
|
|
|
|
{
|
|
|
|
t.XStep()
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
{
|
|
|
|
t.YStep()
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename...> using void_ = void;
|
|
|
|
|
|
|
|
template<class D, bool R> struct GetReadType_;
|
|
|
|
|
|
|
|
template<class D> struct GetReadType_<D, true>
|
|
|
|
{
|
|
|
|
using type = typename D::Data;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class D> struct GetReadType_<D, false>
|
|
|
|
{
|
|
|
|
using type = std::decay_t<D>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept HaveDisable = requires(T t) {
|
|
|
|
{
|
|
|
|
T::disabledactions
|
|
|
|
} -> std::convertible_to<const char*>;
|
|
|
|
};
|
|
|
|
|
|
|
|
consteval bool cmpspace(const char* s1, const char* s2)
|
|
|
|
{
|
|
|
|
size_t i = 0;
|
|
|
|
while(true)
|
|
|
|
{
|
|
|
|
if(s1[i] != s2[i]) return false;
|
|
|
|
i++;
|
|
|
|
if(s1[i] == 0 && (s2[i] == 0 || s2[i] == ' ')) return true;
|
|
|
|
if(s1[i] == 0 || s2[i] == 0 || s2[i] == ' ') return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} // namespace internal
|
|
|
|
|
|
|
|
template<class Act, class S> consteval bool IsDisabled()
|
|
|
|
{
|
|
|
|
if constexpr(!internal::HaveDisable<S>)
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool prsp = true;
|
|
|
|
size_t i = 0;
|
|
|
|
do {
|
|
|
|
if(prsp && internal::cmpspace(Act::name, S::disabledactions + i)) return true;
|
|
|
|
prsp = S::disabledactions[i] == ' ';
|
|
|
|
} while(S::disabledactions[++i] != 0);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class D> using ReadType = internal::GetReadType_<D, ReadPSupported<D> || ReadSupported<D>>::type;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ReadIsGrid = requires {
|
|
|
|
{
|
|
|
|
std::declval<ReadType<T>>().XStep()
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
{
|
|
|
|
std::declval<ReadType<T>>().YStep()
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ReadIs2DGeoRectArray = requires {
|
|
|
|
{
|
|
|
|
std::declval<ReadType<T>>().Ix2Lon(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
{
|
|
|
|
std::declval<ReadType<T>>().Iy2Lat(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ReadIs2DGeoArray = requires {
|
|
|
|
{
|
|
|
|
std::declval<ReadType<T>>().Lon(0, 0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
{
|
|
|
|
std::declval<ReadType<T>>().Lat(0, 0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept ReadIs1DGeoArray = requires {
|
|
|
|
{
|
|
|
|
std::declval<ReadType<T>>().Lon(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
{
|
|
|
|
std::declval<ReadType<T>>().Lat(0)
|
|
|
|
} -> std::convertible_to<real>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
concept CanInterpolate2D = requires {
|
|
|
|
{
|
|
|
|
std::declval<ReadType<T>>().GridPoint(0.0, 0.0)
|
|
|
|
} -> std::convertible_to<struct GridPointLocation>;
|
|
|
|
};
|