GEGELATI
lambdaInstruction.h
1
38#ifndef LAMBDA_INSTRUCTION_H
39#define LAMBDA_INSTRUCTION_H
40
41#include <functional>
42#include <typeinfo>
43
44#include "data/untypedSharedPtr.h"
45#include "instructions/instruction.h"
46
47namespace Instructions {
48
59 template <typename First, typename... Rest>
61 {
62
63#ifdef CODE_GENERATION
64 public:
75 LambdaInstruction(std::function<double(First, Rest...)> function,
76 const std::string& printTemplate = "")
78 {
79 setUpOperand();
80 };
81
82#endif // CODE_GENERATION
83 protected:
87 const std::function<double(const First, const Rest...)> func;
88
89 public:
94#ifndef CODE_GENERATION
103 LambdaInstruction(std::function<double(First, Rest...)> function)
104 : Instructions::Instruction(), func{function}
105 {
106 setUpOperand();
107 };
108#endif // CODE_GENERATION
110 virtual bool checkOperandTypes(
111 const std::vector<Data::UntypedSharedPtr>& arguments) const override
112 {
113 if (arguments.size() != this->operandTypes.size()) {
114 return false;
115 }
116
117 // List of expected types
118 const std::vector<std::reference_wrapper<const std::type_info>>
119 expectedTypes{
120 // First
121 (!std::is_array<First>::value)
122 ? typeid(First)
123 : typeid(std::remove_all_extents_t<First>[]),
124 (!std::is_array<Rest>::value)
125 ? typeid(Rest)
126 : typeid(std::remove_all_extents_t<Rest>[])...};
127
128 for (auto idx = 0; idx < arguments.size(); idx++) {
129 // Argument Type
130 const std::type_info& argType = arguments.at(idx).getType();
131 if (argType != expectedTypes.at(idx).get()) {
132 return false;
133 }
134 }
135
136 return true;
137 };
138
140 virtual double execute(
141 const std::vector<Data::UntypedSharedPtr>& args) const override
142 {
143
144#ifndef NDEBUG
145 if (Instruction::execute(args) != 1.0) {
146 return 0.0;
147 }
148#endif
149 double result =
150 doExecution(args, std::index_sequence_for<Rest...>{});
151
152 return result;
153 };
154
155 private:
170 template <size_t... I>
171 double doExecution(const std::vector<Data::UntypedSharedPtr>& args,
172 std::index_sequence<I...>) const
173 {
174 return this->func(
175 getDataFromUntypedSharedPtr<First>(args, 0),
176 getDataFromUntypedSharedPtr<Rest>(args, I + 1)...);
177 }
178
193 template <typename T,
194 typename MINUS_EXTENT = typename std::remove_extent<T>::type,
195 typename RETURN_TYPE = typename std::conditional<
196 !std::is_array<MINUS_EXTENT>::value,
197 typename std::remove_all_extents<T>::type*,
198 MINUS_EXTENT*>::type>
199 constexpr auto getDataFromUntypedSharedPtr(
200 const std::vector<Data::UntypedSharedPtr>& args, size_t idx) const
201 {
202 if constexpr (!std::is_array<T>::value) {
203 return *(args.at(idx).getSharedPointer<const T>());
204 }
205 else {
206 auto returnedPtr =
207 args.at(idx)
208 .getSharedPointer<
209 const std::remove_all_extents_t<T>[]>();
210 return (RETURN_TYPE)returnedPtr.get();
211 };
212 };
213
214 void setUpOperand()
215 {
216 this->operandTypes.push_back(typeid(First));
217 // Fold expression to push all other types
218 (this->operandTypes.push_back(typeid(Rest)), ...);
219 }
220 };
221}; // namespace Instructions
222
223#endif
This abstract class is the base class for any instruction to be used in a Program.
Definition: instruction.h:59
std::vector< std::reference_wrapper< const std::type_info > > operandTypes
List of the types of the operands needed to execute the instruction.
Definition: instruction.h:211
virtual double execute(const std::vector< Data::UntypedSharedPtr > &args) const =0
Execute the Instruction for the given arguments.
Definition: instruction.cpp:81
std::string printTemplate
Definition: instruction.h:110
Template instruction for simplifying the creation of an Instruction from a c++ lambda function.
Definition: lambdaInstruction.h:61
const std::function< double(const First, const Rest...)> func
Function executed for this Instruction.
Definition: lambdaInstruction.h:80
LambdaInstruction()=delete
delete the default constructor.
virtual double execute(const std::vector< Data::UntypedSharedPtr > &args) const override
Inherited from Instruction.
Definition: lambdaInstruction.h:140
LambdaInstruction(std::function< double(First, Rest...)> function, const std::string &printTemplate="")
Constructor of the class LambdaInstruction to create a printable Instruction.
Definition: lambdaInstruction.h:75
Definition: addPrimitiveType.h:48