TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
eval.hpp
Go to the documentation of this file.
1// Copyright (c) 2019-2023 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Olivier Parcollet, Nils Wentzell
16
22#pragma once
23
24#include "./expression.hpp"
25#include "./operation.hpp"
26#include "./placeholder.hpp"
27#include "./utils.hpp"
28#include "../macros.hpp"
29
30#include <functional>
31#include <tuple>
32#include <type_traits>
33#include <utility>
34
35namespace nda::clef {
36
43 // Forward declarations.
44 template <typename T, typename... Pairs>
45 decltype(auto) eval(T const &obj, Pairs &&...pairs);
47
54 template <typename T, typename... Pairs>
55 struct evaluator {
57 static constexpr bool is_lazy = is_any_lazy<T>;
58
65 FORCEINLINE T const &operator()(T const &t, Pairs &...) const { return t; }
66 };
67
75 template <int N, int... Is, typename... Ts>
76 struct evaluator<placeholder<N>, pair<Is, Ts>...> {
77 private:
78 // Helper function to determine the position of the nda::clef::pair that has the nda::clef::placeholder<N>.
79 template <size_t... Ps>
80 static constexpr int get_position_of_N(std::index_sequence<Ps...>) {
81 return ((Is == N ? int(Ps) + 1 : 0) + ...) - 1;
82 }
83
84 // The position of the nda::clef::pair that has the nda::clef::placeholder<N> (-1 if no such pair was given).
85 static constexpr int N_position = get_position_of_N(std::make_index_sequence<sizeof...(Is)>{});
86
87 public:
92 static constexpr bool is_lazy = (N_position == -1);
93
101 FORCEINLINE decltype(auto) operator()(placeholder<N>, pair<Is, Ts> &...pairs) const {
102 if constexpr (not is_lazy) { // N is one of the Is
103 auto &pair_N = std::get<N_position>(std::tie(pairs...));
104 // the pair is a temporary constructed for the time of the eval call
105 // if it holds a reference, we return it, else we move the rhs object out of the pair
106 if constexpr (std::is_lvalue_reference_v<decltype(pair_N.rhs)>) {
107 return pair_N.rhs;
108 } else {
109 return std::move(pair_N.rhs);
110 }
111 } else { // N is not one of the Is
112 return placeholder<N>{};
113 }
114 }
115 };
116
123 template <typename T, typename... Pairs>
124 struct evaluator<std::reference_wrapper<T>, Pairs...> {
126 static constexpr bool is_lazy = false;
127
135 FORCEINLINE decltype(auto) operator()(std::reference_wrapper<T> const &wrapper, Pairs const &...pairs) const {
136 return eval(wrapper.get(), pairs...);
137 }
138 };
139
147 template <typename Tag, typename... Childs, typename... Pairs>
148 struct evaluator<expr<Tag, Childs...>, Pairs...> {
150 static constexpr bool is_lazy = (evaluator<Childs, Pairs...>::is_lazy or ...);
151
152 private:
153 // Helper function to evaluate the given expression.
154 template <size_t... Is>
155 [[nodiscard]] FORCEINLINE decltype(auto) eval_impl(std::index_sequence<Is...>, expr<Tag, Childs...> const &ex, Pairs &...pairs) const {
156 return op_dispatch<Tag>(std::integral_constant<bool, is_lazy>{}, eval(std::get<Is>(ex.childs), pairs...)...);
157 }
158
159 public:
170 [[nodiscard]] FORCEINLINE decltype(auto) operator()(expr<Tag, Childs...> const &ex, Pairs &...pairs) const {
171 return eval_impl(std::make_index_sequence<sizeof...(Childs)>(), ex, pairs...);
172 }
173 };
174
196 template <typename T, typename... Pairs>
197 FORCEINLINE decltype(auto) eval(T const &obj, Pairs &&...pairs) { // NOLINT (we don't want to forward here)
198 return evaluator<T, std::remove_reference_t<Pairs>...>()(obj, pairs...);
199 }
200
203} // namespace nda::clef
Provides a basic lazy expression type for the clef library.
__inline__ decltype(auto) eval(T const &obj, Pairs &&...pairs)
Generic function to evaluate expressions and other types.
Definition eval.hpp:197
__inline__ auto op_dispatch(std::true_type, Args &&...args)
Dispatch operations containing at least one lazy operand.
constexpr bool is_any_lazy
Constexpr variable that is true if any of the given types is lazy.
Definition utils.hpp:157
Macros used in the nda library.
Provides operations for the clef library.
Provides placeholders for the clef library.
Generic evaluator for types which do not have a specialized evaluator.
Definition eval.hpp:55
__inline__ T const & operator()(T const &t, Pairs &...) const
Evaluate the object and ignore all given nda::clef::pair objects.
Definition eval.hpp:65
static constexpr bool is_lazy
Constexpr variable that is true if the type T is lazy.
Definition eval.hpp:57
Single node of the expression tree.
childs_t childs
Child nodes of the current expression node.
A pair consisting of a placeholder and its assigned value.
A placeholder is an empty struct, labelled by an int.
Provides some utility functions and type traits for the CLEF library.