Skip to content

Commit

Permalink
Replace enable_if with concepts
Browse files Browse the repository at this point in the history
  • Loading branch information
fintarin committed Sep 21, 2023
1 parent 5eda355 commit e1b61a6
Show file tree
Hide file tree
Showing 19 changed files with 112 additions and 157 deletions.
1 change: 1 addition & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ AllowShortLambdasOnASingleLine: true
AllowAllParametersOfDeclarationOnNextLine: true
NamespaceIndentation: None
IndentCaseLabels: True
IndentRequires: True
FixNamespaceComments: false
BreakBeforeBraces: Custom
BraceWrapping:
Expand Down
21 changes: 7 additions & 14 deletions include/fintamath/core/Converter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,18 @@

#include "fintamath/core/MultiMethod.hpp"

#define REQUIRE_MATH_OBJECTS(To, From) \
template <typename To, typename From, \
typename = std::enable_if_t<std::is_base_of_v<IMathObject, To> && \
std::is_base_of_v<IMathObject, From>>>

namespace fintamath {

class IMathObject;

class Converter {
REQUIRE_MATH_OBJECTS(Type, Value)
using ConverterFunction = std::function<std::unique_ptr<IMathObject>(const Type &type, const Value &value)>;
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
using ConverterFunction = std::function<std::unique_ptr<IMathObject>(const To &to, const From &from)>;

public:
REQUIRE_MATH_OBJECTS(Type, Value)
static void add(const ConverterFunction<Type, Value> &convertFunc) {
getConverter().add<Type, Value>(convertFunc);
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
static void add(const ConverterFunction<To, From> &convertFunc) {
getConverter().add<To, From>(convertFunc);
}

static std::unique_ptr<IMathObject> convert(const IMathObject &to, const IMathObject &from) {
Expand All @@ -31,17 +26,15 @@ class Converter {
static MultiMethod<std::unique_ptr<IMathObject>(const IMathObject &, const IMathObject &)> &getConverter();
};

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
std::unique_ptr<To> convert(const To &to, const From &from) {
return cast<To>(Converter::convert(to, from));
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
std::unique_ptr<To> convert(const From &from) {
static const To to;
return convert(to, from);
}

}

#undef REQUIRE_MATH_OBJECTS
38 changes: 17 additions & 21 deletions include/fintamath/core/CoreUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@

#include "fintamath/core/MathObjectTypes.hpp"

#define REQUIRE_MATH_OBJECTS(To, From) \
template <typename To, typename From, \
typename = std::enable_if_t<std::is_base_of_v<IMathObject, To> && \
std::is_base_of_v<IMathObject, From>>>

namespace fintamath {

class IMathObject;

REQUIRE_MATH_OBJECTS(To, From)
template <typename From, typename To>
concept convertible_to_and_not_same_as = std::convertible_to<From, To> && !std::same_as<From, To>;

template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
bool is(const From &from) {
if constexpr (std::is_base_of_v<To, From>) {
return true;
Expand All @@ -26,7 +24,7 @@ bool is(const From &from) {
}
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
bool is(const From *from) {
if (!from) {
return false;
Expand All @@ -35,32 +33,32 @@ bool is(const From *from) {
return is<To>(*from);
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
bool is(const std::unique_ptr<From> &from) {
return is<To>(from.get());
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
bool is(const std::shared_ptr<From> &from) {
return is<To>(from.get());
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
bool is(const std::shared_ptr<const From> &from) {
return is<To>(from.get());
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
bool is(const std::reference_wrapper<From> &from) {
return is<To>(from.get());
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
bool is(const std::reference_wrapper<const From> &from) {
return is<To>(from.get());
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
const To &cast(const From &from) {
if constexpr (!std::is_base_of_v<To, From>) {
if (!is<To>(from)) {
Expand All @@ -71,12 +69,12 @@ const To &cast(const From &from) {
return static_cast<const To &>(from);
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
To &cast(From &from) {
return const_cast<To &>(cast<To>(const_cast<const From &>(from)));
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
const To *cast(const From *from) {
if constexpr (!std::is_base_of_v<To, From>) {
if (!is<To>(from)) {
Expand All @@ -87,12 +85,12 @@ const To *cast(const From *from) {
return static_cast<const To *>(from);
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
To *cast(From *from) {
return const_cast<To *>(cast<To>(const_cast<const From *>(from)));
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
std::unique_ptr<To> cast(std::unique_ptr<From> &&from) {
if constexpr (!std::is_base_of_v<To, From>) {
if (!is<To>(from)) {
Expand All @@ -106,7 +104,7 @@ std::unique_ptr<To> cast(std::unique_ptr<From> &&from) {
return std::unique_ptr<To>(toRawPtr);
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
std::shared_ptr<const To> cast(const std::shared_ptr<const From> &from) {
if constexpr (!std::is_base_of_v<To, From>) {
if (!is<To>(from)) {
Expand All @@ -117,11 +115,9 @@ std::shared_ptr<const To> cast(const std::shared_ptr<const From> &from) {
return std::static_pointer_cast<const To>(from);
}

REQUIRE_MATH_OBJECTS(To, From)
template <std::derived_from<IMathObject> To, std::derived_from<IMathObject> From>
std::shared_ptr<To> cast(const std::shared_ptr<From> &from) {
return std::const_pointer_cast<To>(cast<To>(std::const_pointer_cast<const From>(from)));
}

}

#undef REQUIRE_MATH_OBJECTS
36 changes: 14 additions & 22 deletions include/fintamath/core/IArithmetic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
#include "fintamath/exceptions/InvalidInputException.hpp"
#include "fintamath/parser/Parser.hpp"

#define REQUIRE_ARITHMETICS(Lhs, Rhs) \
template <typename Lhs, typename Rhs, \
typename = std::enable_if_t<std::is_base_of_v<IArithmetic, Lhs> && \
std::is_convertible_v<Rhs, Lhs> && \
!std::is_same_v<Lhs, Rhs>>>

namespace fintamath {

class IArithmetic : public IMathObject {
Expand Down Expand Up @@ -38,12 +32,12 @@ class IArithmetic : public IMathObject {
return rhs.negateAbstract();
}

template <typename T, typename = std::enable_if_t<std::is_base_of_v<IArithmetic, T>>>
template <std::derived_from<IArithmetic> T>
static void registerType() {
Parser::registerType<T>(getParser());
}

template <typename T, typename = std::enable_if_t<std::is_base_of_v<IArithmetic, T>>>
template <std::derived_from<IArithmetic> T>
static void registerType(Parser::Function<std::unique_ptr<IArithmetic>, const std::string &> &&parserFunc) {
Parser::registerType<T>(getParser(), std::move(parserFunc));
}
Expand Down Expand Up @@ -80,66 +74,64 @@ class IArithmeticCRTP : public IArithmetic {
#undef I_ARITHMETIC_CRTP
};

REQUIRE_ARITHMETICS(Lhs, Rhs)
template <std::derived_from<IArithmetic> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
Lhs &operator+=(Lhs &lhs, const Rhs &rhs) {
return lhs += Lhs(rhs);
}

REQUIRE_ARITHMETICS(Lhs, Rhs)
template <std::derived_from<IArithmetic> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
Lhs &operator-=(Lhs &lhs, const Rhs &rhs) {
return lhs -= Lhs(rhs);
}

REQUIRE_ARITHMETICS(Lhs, Rhs)
template <std::derived_from<IArithmetic> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
Lhs &operator*=(Lhs &lhs, const Rhs &rhs) {
return lhs *= Lhs(rhs);
}

REQUIRE_ARITHMETICS(Lhs, Rhs)
template <std::derived_from<IArithmetic> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
Lhs &operator/=(Lhs &lhs, const Rhs &rhs) {
return lhs /= Lhs(rhs);
}

REQUIRE_ARITHMETICS(Lhs, Rhs)
template <std::derived_from<IArithmetic> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
Lhs operator+(const Lhs &lhs, const Rhs &rhs) {
return lhs + Lhs(rhs);
}

REQUIRE_ARITHMETICS(Rhs, Lhs)
template <std::derived_from<IArithmetic> Rhs, convertible_to_and_not_same_as<Rhs> Lhs>
Rhs operator+(const Lhs &lhs, const Rhs &rhs) {
return Rhs(lhs) + rhs;
}

REQUIRE_ARITHMETICS(Lhs, Rhs)
template <std::derived_from<IArithmetic> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
Lhs operator-(const Lhs &lhs, const Rhs &rhs) {
return lhs - Lhs(rhs);
}

REQUIRE_ARITHMETICS(Rhs, Lhs)
template <std::derived_from<IArithmetic> Rhs, convertible_to_and_not_same_as<Rhs> Lhs>
Rhs operator-(const Lhs &lhs, const Rhs &rhs) {
return Rhs(lhs) - rhs;
}

REQUIRE_ARITHMETICS(Lhs, Rhs)
template <std::derived_from<IArithmetic> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
Lhs operator*(const Lhs &lhs, const Rhs &rhs) {
return lhs * Lhs(rhs);
}

REQUIRE_ARITHMETICS(Rhs, Lhs)
template <std::derived_from<IArithmetic> Rhs, convertible_to_and_not_same_as<Rhs> Lhs>
Rhs operator*(const Lhs &lhs, const Rhs &rhs) {
return Rhs(lhs) * rhs;
}

REQUIRE_ARITHMETICS(Lhs, Rhs)
template <std::derived_from<IArithmetic> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
Lhs operator/(const Lhs &lhs, const Rhs &rhs) {
return lhs / Lhs(rhs);
}

REQUIRE_ARITHMETICS(Rhs, Lhs)
template <std::derived_from<IArithmetic> Rhs, convertible_to_and_not_same_as<Rhs> Lhs>
Rhs operator/(const Lhs &lhs, const Rhs &rhs) {
return Rhs(lhs) / rhs;
}

}

#undef REQUIRE_ARITHMETICS
12 changes: 2 additions & 10 deletions include/fintamath/core/IComparable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
#include "fintamath/exceptions/InvalidInputException.hpp"
#include "fintamath/parser/Parser.hpp"

#define REQUIRE_COMPARABLES(Lhs, Rhs) \
template <typename Lhs, typename Rhs, \
typename = std::enable_if_t<std::is_base_of_v<IComparable, Lhs> && \
std::is_convertible_v<Rhs, Lhs> && \
!std::is_same_v<Lhs, Rhs>>>

namespace fintamath {

class IComparable : public IArithmetic {
Expand All @@ -18,7 +12,7 @@ class IComparable : public IArithmetic {
return lhs.compareAbstract(rhs);
}

template <typename T, typename = std::enable_if_t<std::is_base_of_v<IComparable, T>>>
template <std::derived_from<IComparable> T>
static void registerType(Parser::Function<std::unique_ptr<IComparable>, const std::string &> &&parserFunc) {
Parser::registerType<T>(getParser(), std::move(parserFunc));
}
Expand All @@ -45,11 +39,9 @@ class IComparableCRTP : public IComparable {
#undef I_COMPARABLE_CRTP
};

REQUIRE_COMPARABLES(Lhs, Rhs)
template <std::derived_from<IComparable> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
std::strong_ordering operator<=>(const Lhs &lhs, const Rhs &rhs) {
return lhs <=> Lhs(rhs);
}

}

#undef REQUIRE_COMPARABLES
12 changes: 2 additions & 10 deletions include/fintamath/core/IMathObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@
#include "fintamath/core/CoreUtils.hpp"
#include "fintamath/parser/Parser.hpp"

#define REQUIRE_MATH_OBJECTS(Lhs, Rhs) \
template <typename Lhs, typename Rhs, \
typename = std::enable_if_t<std::is_base_of_v<IMathObject, Lhs> && \
std::is_convertible_v<Rhs, Lhs> && \
!std::is_same_v<Lhs, Rhs>>>

namespace fintamath {

class IMathObject {
Expand All @@ -41,7 +35,7 @@ class IMathObject {
return lhs.equalsAbstract(rhs);
}

template <typename T, typename = std::enable_if_t<std::is_base_of_v<IMathObject, T>>>
template <std::derived_from<IMathObject> T>
static void registerType(Parser::Function<std::unique_ptr<IMathObject>, const std::string &> &&parserFunc) {
Parser::registerType<T>(getParser(), std::move(parserFunc));
}
Expand All @@ -68,7 +62,7 @@ class IMathObjectCRTP : public IMathObject {
#undef I_MATH_OBJECT_CRTP
};

REQUIRE_MATH_OBJECTS(Lhs, Rhs)
template <std::derived_from<IMathObject> Lhs, convertible_to_and_not_same_as<Lhs> Rhs>
bool operator==(const Lhs &lhs, const Rhs &rhs) {
return lhs == Lhs(rhs);
}
Expand All @@ -78,5 +72,3 @@ inline std::ostream &operator<<(std::ostream &out, const IMathObject &rhs) {
}

}

#undef REQUIRE_MATH_OBJECTS
7 changes: 3 additions & 4 deletions include/fintamath/core/MultiMethod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@ class MultiMethod<Res(ArgsBase...)> {
using Callbacks = std::map<CallbackId, Callback>;

public:
template <typename... Args, typename Func>
void add(const Func &func) {
template <typename... Args>
void add(const auto &func) {
callbacks[CallbackId(Args::getTypeStatic()...)] = [func](const ArgsBase &...args) {
return func(cast<Args>(args)...);
};
}

template <typename... Args>
Res operator()(const Args &...args) const {
Res operator()(const auto &...args) const {
auto it = callbacks.find(CallbackId(args.getType()...));

if (it != callbacks.end()) {
Expand Down
6 changes: 3 additions & 3 deletions include/fintamath/expressions/Expression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ class Expression : public IExpressionCRTP<Expression> {
Parser::add<Token>(getTermMakers(), std::move(maker));
}

template <typename Function, bool isPolynomial = false, typename Maker>
static void registerFunctionExpressionMaker(Maker &&maker) {
template <typename Function, bool isPolynomial = false>
static void registerFunctionExpressionMaker(auto &&maker) {
Parser::Function<std::unique_ptr<IMathObject>, const ArgumentsPtrVector &> constructor =
[maker = std::forward<Maker>(maker)](const ArgumentsPtrVector &args)
[maker = std::forward<decltype(maker)>(maker)](const ArgumentsPtrVector &args)
-> std::unique_ptr<IMathObject> {
//
static const IFunction::Type type = Function().getFunctionType();
Expand Down
2 changes: 1 addition & 1 deletion include/fintamath/expressions/IExpression.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class IExpression : public IArithmetic {

virtual std::shared_ptr<IFunction> getOutputFunction() const;

template <typename T, typename = std::enable_if_t<std::is_base_of_v<IExpression, T>>>
template <std::derived_from<IExpression> T>
static void registerType() {
Parser::registerType<T>(getParser());
}
Expand Down
Loading

0 comments on commit e1b61a6

Please sign in to comment.