136 lines
10 KiB
C++
136 lines
10 KiB
C++
/*
|
|
This file is part of KDBindings.
|
|
|
|
SPDX-FileCopyrightText: 2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
|
Author: Sean Harmer <sean.harmer@kdab.com>
|
|
|
|
SPDX-License-Identifier: MIT
|
|
|
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <kdbindings/node.h>
|
|
#include <kdbindings/make_node.h>
|
|
|
|
namespace KDBindings {
|
|
|
|
// Helper macro to declare free standing unary operators for Property and Node
|
|
|
|
#define KDBINDINGS_DEFINE_UNARY_OP(OP) \
|
|
template<typename... T> \
|
|
inline auto operator OP(Property<T...> &arg) noexcept(noexcept(OP arg.get())) \
|
|
->Private::Node<std::decay_t<decltype(OP arg.get())>> \
|
|
{ \
|
|
return Private::makeNode([](auto &&v) { return (OP v); }, arg); \
|
|
} \
|
|
\
|
|
template<typename T> \
|
|
inline auto operator OP(Private::Node<T> &&arg) noexcept(noexcept(OP arg.evaluate())) \
|
|
->Private::Node<std::decay_t<decltype(OP arg.evaluate())>> \
|
|
{ \
|
|
return Private::makeNode([](auto &&v) { return (OP v); }, std::move(arg)); \
|
|
}
|
|
|
|
KDBINDINGS_DEFINE_UNARY_OP(!)
|
|
KDBINDINGS_DEFINE_UNARY_OP(~) // Bitwise not
|
|
KDBINDINGS_DEFINE_UNARY_OP(+)
|
|
KDBINDINGS_DEFINE_UNARY_OP(-)
|
|
|
|
// Helper macro to declare free standing binary operators for Property and Node.
|
|
// The combinations we need are:
|
|
//
|
|
// operator op (Property<A> &a, B&& b) [Property, value]
|
|
// operator op (A&& a, Property<B> &b) [value, Property]
|
|
// operator op (Property<A> &a, Property<B> &b) [Property, Property]
|
|
//
|
|
// operator op (Node<A>&& a, B&& b) [Node value]
|
|
// operator op (A&& a, Node<B>&& b) [value, Node]
|
|
// operator op (Node<A>&& a, Node<B>&& b) [Node, Node]
|
|
//
|
|
// operator op (Property<A> &a, Node<B>&& b) [Property, Node]
|
|
// operaotr op (Node<A>&& a, Property<B> &b) [Node, Property]
|
|
|
|
#define KDBINDINGS_DEFINE_BINARY_OP(OP) \
|
|
template<typename B, typename... A> \
|
|
inline auto operator OP(Property<A...> &a, B &&b) noexcept(noexcept(a.get() OP b)) \
|
|
->std::enable_if_t<!Private::is_bindable<B>::value, \
|
|
Private::Node<decltype(a.get() OP b)>> \
|
|
{ \
|
|
return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, a, std::forward<B>(b)); \
|
|
} \
|
|
\
|
|
template<typename A, typename... B> \
|
|
inline auto operator OP(A &&a, Property<B...> &b) noexcept(noexcept(a OP b.get())) \
|
|
->std::enable_if_t<!Private::is_bindable<A>::value, \
|
|
Private::Node<decltype(a OP b.get())>> \
|
|
{ \
|
|
return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, std::forward<A>(a), b); \
|
|
} \
|
|
\
|
|
template<typename A, typename B> \
|
|
inline auto operator OP(Property<A> &a, Property<B> &b) noexcept(noexcept(a.get() OP b.get())) \
|
|
->Private::Node<decltype(a.get() OP b.get())> \
|
|
{ \
|
|
return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, a, b); \
|
|
} \
|
|
\
|
|
template<typename A, typename B> \
|
|
inline auto operator OP(Private::Node<A> &&a, B &&b) noexcept(noexcept(a.evaluate() OP b)) \
|
|
->std::enable_if_t<!Private::is_bindable<B>::value, \
|
|
Private::Node<decltype(a.evaluate() OP b)>> \
|
|
{ \
|
|
return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, std::move(a), std::forward<B>(b)); \
|
|
} \
|
|
\
|
|
template<typename A, typename B> \
|
|
inline auto operator OP(A &&a, Private::Node<B> &&b) noexcept(noexcept(a OP b.evaluate())) \
|
|
->std::enable_if_t<!Private::is_bindable<A>::value, \
|
|
Private::Node<decltype(a OP b.evaluate())>> \
|
|
{ \
|
|
return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, std::forward<A>(a), std::move(b)); \
|
|
} \
|
|
\
|
|
template<typename A, typename B> \
|
|
inline auto operator OP(Private::Node<A> &&a, Private::Node<B> &&b) noexcept(noexcept(a.evaluate() OP b.evaluate())) \
|
|
->Private::Node<decltype(a.evaluate() OP b.evaluate())> \
|
|
{ \
|
|
return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, std::move(a), std::move(b)); \
|
|
} \
|
|
\
|
|
template<typename B, typename A> \
|
|
inline auto operator OP(Property<A> &a, Private::Node<B> &&b) noexcept(noexcept(a.get() OP b.evaluate())) \
|
|
->Private::Node<decltype(a.get() OP b.evaluate())> \
|
|
{ \
|
|
return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, a, std::move(b)); \
|
|
} \
|
|
\
|
|
template<typename A, typename B> \
|
|
inline auto operator OP(Private::Node<A> &&a, Property<B> &b) noexcept(noexcept(a.evaluate() OP b.get())) \
|
|
->Private::Node<decltype(a.evaluate() OP b.get())> \
|
|
{ \
|
|
return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, std::move(a), b); \
|
|
}
|
|
|
|
KDBINDINGS_DEFINE_BINARY_OP(*)
|
|
KDBINDINGS_DEFINE_BINARY_OP(/)
|
|
KDBINDINGS_DEFINE_BINARY_OP(%)
|
|
KDBINDINGS_DEFINE_BINARY_OP(+)
|
|
KDBINDINGS_DEFINE_BINARY_OP(-)
|
|
KDBINDINGS_DEFINE_BINARY_OP(<<)
|
|
KDBINDINGS_DEFINE_BINARY_OP(>>)
|
|
KDBINDINGS_DEFINE_BINARY_OP(<)
|
|
KDBINDINGS_DEFINE_BINARY_OP(<=)
|
|
KDBINDINGS_DEFINE_BINARY_OP(>)
|
|
KDBINDINGS_DEFINE_BINARY_OP(>=)
|
|
KDBINDINGS_DEFINE_BINARY_OP(==)
|
|
KDBINDINGS_DEFINE_BINARY_OP(!=)
|
|
KDBINDINGS_DEFINE_BINARY_OP(&)
|
|
KDBINDINGS_DEFINE_BINARY_OP(^)
|
|
KDBINDINGS_DEFINE_BINARY_OP(|)
|
|
KDBINDINGS_DEFINE_BINARY_OP(&&)
|
|
KDBINDINGS_DEFINE_BINARY_OP(||)
|
|
|
|
} // namespace KDBindings
|