/* This file is part of KDBindings. SPDX-FileCopyrightText: 2021 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Sean Harmer SPDX-License-Identifier: MIT Contact KDAB at for commercial licensing options. */ #pragma once #include #include namespace KDBindings { // Helper macro to declare free standing unary operators for Property and Node #define KDBINDINGS_DEFINE_UNARY_OP(OP) \ template \ inline auto operator OP(Property &arg) noexcept(noexcept(OP arg.get())) \ ->Private::Node> \ { \ return Private::makeNode([](auto &&v) { return (OP v); }, arg); \ } \ \ template \ inline auto operator OP(Private::Node &&arg) noexcept(noexcept(OP arg.evaluate())) \ ->Private::Node> \ { \ 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, B&& b) [Property, value] // operator op (A&& a, Property &b) [value, Property] // operator op (Property &a, Property &b) [Property, Property] // // operator op (Node&& a, B&& b) [Node value] // operator op (A&& a, Node&& b) [value, Node] // operator op (Node&& a, Node&& b) [Node, Node] // // operator op (Property &a, Node&& b) [Property, Node] // operaotr op (Node&& a, Property &b) [Node, Property] #define KDBINDINGS_DEFINE_BINARY_OP(OP) \ template \ inline auto operator OP(Property &a, B &&b) noexcept(noexcept(a.get() OP b)) \ ->std::enable_if_t::value, \ Private::Node> \ { \ return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, a, std::forward(b)); \ } \ \ template \ inline auto operator OP(A &&a, Property &b) noexcept(noexcept(a OP b.get())) \ ->std::enable_if_t::value, \ Private::Node> \ { \ return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, std::forward(a), b); \ } \ \ template \ inline auto operator OP(Property &a, Property &b) noexcept(noexcept(a.get() OP b.get())) \ ->Private::Node \ { \ return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, a, b); \ } \ \ template \ inline auto operator OP(Private::Node &&a, B &&b) noexcept(noexcept(a.evaluate() OP b)) \ ->std::enable_if_t::value, \ Private::Node> \ { \ return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, std::move(a), std::forward(b)); \ } \ \ template \ inline auto operator OP(A &&a, Private::Node &&b) noexcept(noexcept(a OP b.evaluate())) \ ->std::enable_if_t::value, \ Private::Node> \ { \ return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, std::forward(a), std::move(b)); \ } \ \ template \ inline auto operator OP(Private::Node &&a, Private::Node &&b) noexcept(noexcept(a.evaluate() OP b.evaluate())) \ ->Private::Node \ { \ return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, std::move(a), std::move(b)); \ } \ \ template \ inline auto operator OP(Property &a, Private::Node &&b) noexcept(noexcept(a.get() OP b.evaluate())) \ ->Private::Node \ { \ return Private::makeNode([](auto &&av, auto &&bv) { return (av OP bv); }, a, std::move(b)); \ } \ \ template \ inline auto operator OP(Private::Node &&a, Property &b) noexcept(noexcept(a.evaluate() OP b.get())) \ ->Private::Node \ { \ 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