Empirical
attrs.h
Go to the documentation of this file.
1 #ifndef EMP_PLOT_EMP
2 #define EMP_PLOT_EMP
3 
4 #include <algorithm>
5 #include <iostream>
6 #include <iterator>
7 #include <memory>
8 #include <utility>
9 #include <vector>
10 
11 #include "meta/TypePack.h"
12 #include "meta/type_traits.h"
13 
14 namespace emp {
15  namespace tools {
16 
17  struct value_tag {};
18 
19  template <typename V1, typename V2>
21  : std::is_same<typename V1::attribute_t, typename V2::attribute_t> {};
22 
23  template <typename T>
24  struct is_attribute_value : std::is_base_of<value_tag, T> {};
25  template <typename T>
27 
28  template <typename...>
29  class Attrs;
30 
31  template <typename T>
32  struct is_attributes_pack : std::false_type {};
33  template <typename... U>
34  struct is_attributes_pack<Attrs<U...>> : std::true_type {};
35 
36  template <typename T>
38 
39  namespace __impl_has_attr {
40  template <typename Pack, typename Attr>
41  struct has_attribute {
42  template <typename T>
43  static constexpr std::true_type HasAttr(
44  const typename Attr::template value_t<T>&) {
45  return {};
46  }
47  static constexpr std::false_type HasAttr(...) { return {}; }
48 
49  using type = decltype(HasAttr(std::declval<Pack>()));
50  };
51  } // namespace __impl_has_attr
52 
53  template <typename Pack, typename Attr>
54  struct has_attribute : __impl_has_attr::has_attribute<Pack, Attr>::type {};
55  template <typename Pack, typename Attr>
57 
58  namespace __impl_attr_base {
59  template <typename Attr, template <typename> class Value>
60  struct AttrBase {
61  using attribute_t = Attr;
62  template <typename T>
63  using value_t = Value<T>;
64 
65  static constexpr struct get_attribute_t {
68  template <class T>
69  constexpr decltype(auto) operator()(value_t<T>& value) const {
70  return value;
71  }
72 
73  template <class T>
74  constexpr decltype(auto) operator()(const value_t<T>& value) const {
75  return value;
76  }
77 
78  template <class T>
79  constexpr decltype(auto) operator()(value_t<T>&& value) const {
80  return std::move(value);
81  }
82 
83  template <class T>
84  constexpr decltype(auto) operator()(const value_t<T>&& value) const {
85  return std::move(value);
86  }
87  } GetAttribute{};
88 
97  static constexpr struct get_t {
98  template <class T>
99  constexpr const T& operator()(const value_t<T>& target) const {
100  return *target;
101  }
102 
103  template <class T>
104  constexpr T& operator()(value_t<T>& target) const {
105  return *target;
106  }
107 
108  template <class T>
109  constexpr T&& operator()(value_t<T>&& target) const {
110  return *std::move(target);
111  }
112 
113  template <class T>
114  constexpr const T&& operator()(const value_t<T>&& target) const {
115  return *std::move(target);
116  }
117  } Get{};
118 
119  // -- CallOrGet --
120  private:
121  // Handle the case when Get(target) is callable
122  template <class T, class... U>
123  static constexpr auto __impl_CallOrGetAttribute(
124  const std::true_type& isCallable, T&& target, U&&... args) {
125  return Make(Get(std::forward<T>(target))(std::forward<U>(args)...));
126  }
127 
128  // Handle the case when Get(target) is not callable
129  template <class T, class... U>
130  static constexpr auto __impl_CallOrGetAttribute(
131  const std::false_type& isCallable, T&& target, U&&... args) {
132  return GetAttribute(std::forward<T>(target));
133  }
134 
135  public:
140  static constexpr struct call_or_get_attribute_t {
141  template <class V, class... U>
142  constexpr decltype(auto) operator()(V&& target, U&&... args) const {
143  using ValueOfTargetType = decltype(Get(std::forward<V>(target)));
144 
145  return __impl_CallOrGetAttribute(
146  // Check if the target attribute value is invocable
147  emp::is_invocable<ValueOfTargetType,
148  decltype(std::forward<U>(args))...>{},
149  std::forward<V>(target), std::forward<U>(args)...);
150  }
151  } CallOrGetAttribute{};
152 
153  // -- GetOrElse --
154  private:
155  template <typename Pack, typename M, typename D, typename... U>
156  static constexpr decltype(auto) __impl_MapOrElse(const std::true_type&,
157  Pack&& pack, M&& map,
158  D&&, U&&...) {
159  return std::forward<M>(map)(GetAttribute(std::forward<Pack>(pack)));
160  }
161 
162  template <typename Pack, typename M, typename D, typename... U>
163  static constexpr decltype(auto) __impl_MapOrElse(const std::false_type&,
164  Pack&&, M&&,
165  D&& defaultFunction,
166  U&&... args) {
167  return std::forward<D>(defaultFunction)(std::forward<U>(args)...);
168  }
169 
170  public:
171  static constexpr struct map_or_else_t {
172  template <typename Pack, typename M, typename D, typename... U>
173  constexpr decltype(auto) operator()(Pack&& pack, M&& map,
174  D&& defaultFunction,
175  U&&... args) const {
176  return __impl_MapOrElse(
177  has_attribute<std::decay_t<Pack>, attribute_t>{},
178  std::forward<Pack>(pack), std::forward<M>(map),
179  std::forward<D>(defaultFunction), std::forward<U>(args)...);
180  }
181  } MapOrElse{};
182 
183  static constexpr struct get_attribute_or_else_t {
184  template <typename Pack, typename D, typename... U>
185  constexpr decltype(auto) operator()(Pack&& pack, D&& defaultFunction,
186  U&&... args) const {
187  return MapOrElse(std::forward<Pack>(pack), GetAttribute,
188  std::forward<D>(defaultFunction),
189  std::forward<U>(args)...);
190  }
191  } GetAttributeOrElse{};
192 
193  static constexpr struct get_or_else_t {
194  template <class Pack, class F, class... U>
195  constexpr decltype(auto) operator()(Pack&& pack, F&& defaultFunction,
196  U&&... args) const {
197  return MapOrElse(std::forward<Pack>(pack), Get,
198  std::forward<F>(defaultFunction),
199  std::forward<U>(args)...);
200  }
201  } GetOrElse{};
202 
203  private:
204  // Utility class used by GetOr which simply remembers and returns a
205  // value. @todo: when we switch to c++17, we can replace this with a
206  // constexpr closure
207  template <class D>
208  struct Default {
209  D value;
210  constexpr decltype(auto) operator()() const {
211  return std::forward<D>(value);
212  }
213  };
214 
215  public:
216  static constexpr struct get_or_t {
217  template <class Pack, class D>
218  constexpr decltype(auto) operator()(Pack&& pack,
219  D&& defaultValue) const {
220  return GetOrElse(std::forward<Pack>(pack),
221  Default<D&&>{std::forward<D>(defaultValue)});
222  }
223  } GetOr{};
224 
225  private:
226  // Utility class used by GetOrGetIn which simply remembers a attribute
227  // pack.
228  template <typename...>
229  struct FallbackHandler;
230 
231  template <typename Fallback>
232  struct FallbackHandler<Fallback> {
233  Fallback fallback;
234  constexpr FallbackHandler(Fallback fallback)
235  : fallback(std::forward<Fallback>(fallback)) {}
236 
237  constexpr decltype(auto) operator()() const {
238  return GetAttribute(std::forward<Fallback>(fallback));
239  }
240  };
241 
242  template <typename Fallback0, typename Fallback1, typename... Fallbacks>
243  struct FallbackHandler<Fallback0, Fallback1, Fallbacks...> {
244  Fallback0 fallback;
245  FallbackHandler<Fallback1, Fallbacks...> fallbacks;
246  constexpr FallbackHandler(Fallback0&& fallback0,
247  Fallback1&& fallback1,
248  Fallbacks&&... fallbacks)
249  : fallback(std::forward<Fallback0>(fallback0)),
250  fallbacks(std::forward<Fallback1>(fallback1),
251  std::forward<Fallbacks>(fallbacks)...) {}
252 
253  constexpr decltype(auto) operator()() && {
254  return GetAttributeOrElse(std::forward<Fallback0>(fallback),
255  std::move(fallbacks));
256  }
257  };
258 
259  public:
260  static constexpr struct get_attribute_or_get_attribute_in_t {
261  template <class... Fallbacks>
262  constexpr decltype(auto) operator()(Fallbacks&&... fallbacks) const {
263  return FallbackHandler<Fallbacks&&...>{
264  std::forward<Fallbacks>(fallbacks)...}();
265  }
266  } GetAttributeOrGetAttributeIn{};
267 
268  static constexpr struct get_or_get_in_t {
269  template <class... Fallbacks>
270  constexpr decltype(auto) operator()(Fallbacks&&... fallbacks) const {
271  return Get(FallbackHandler<Fallbacks&&...>{
272  std::forward<Fallbacks>(fallbacks)...}());
273  }
274  } GetOrGetIn{};
275  static constexpr struct set_t {
276  template <class T, class V>
277  constexpr void operator()(value_t<T>& target, V&& value) const {
278  Get(target) = std::forward<V>(value);
279  }
280  } Set{};
281 
282  static constexpr struct make_t {
283  template <class T>
284  constexpr value_t<std::decay_t<T>> operator()(T&& value) const {
285  return {std::forward<T>(value)};
286  }
287  } Make{};
288  };
289 
290  template <typename Attr, template <typename> class Value>
291  constexpr typename AttrBase<Attr, Value>::get_attribute_t
293 
294  template <typename Attr, template <typename> class Value>
295  constexpr
297 
298  template <typename Attr, template <typename> class Value>
301 
302  template <typename Attr, template <typename> class Value>
303  constexpr typename AttrBase<Attr, Value>::map_or_else_t
305 
306  template <typename Attr, template <typename> class Value>
309 
310  template <typename Attr, template <typename> class Value>
311  constexpr typename AttrBase<Attr, Value>::get_or_else_t
313 
314  template <typename Attr, template <typename> class Value>
315  constexpr
317 
318  template <typename Attr, template <typename> class Value>
319  constexpr
322 
323  template <typename Attr, template <typename> class Value>
324  constexpr typename AttrBase<Attr, Value>::get_or_get_in_t
326 
327  template <typename Attr, template <typename> class Value>
328  constexpr
330 
331  template <typename Attr, template <typename> class Value>
332  constexpr
334 
335  }; // namespace __impl_attr_base
336 
337 #define DEFINE_ATTR(NAME) \
338  template <class T> \
339  struct NAME##Value; \
340  constexpr struct NAME \
341  : emp::tools::__impl_attr_base::AttrBase<NAME, NAME##Value> { \
342  static constexpr auto name = #NAME; \
343  template <typename T> \
344  constexpr value_t<std::decay_t<T>> operator()(T&& value) const { \
345  return {std::forward<T>(value)}; \
346  } \
347  } NAME; \
348  constexpr const char* NAME::name; \
349  template <class T> \
350  struct NAME##Value : emp::tools::value_tag, NAME { \
351  private: \
352  T value; \
353  \
354  public: \
355  static constexpr auto name = #NAME; \
356  using attribute_t = struct NAME; \
357  using attributes_t = emp::tools::Attrs<NAME##Value<T>>; \
358  using value_t = T; \
359  NAME##Value() = delete; \
360  constexpr NAME##Value(const T& value) : value(value) {} \
361  constexpr NAME##Value(T&& value) : value(std::move(value)) {} \
362  template <typename U = T> \
363  constexpr NAME##Value(const NAME##Value<U>& other) : value(*other) {} \
364  template <typename U = T> \
365  constexpr NAME##Value(NAME##Value<U>&& other) \
366  : value(*std::move(other)) {} \
367  constexpr NAME##Value& operator=(const T& value) { \
368  /* Don't check for self assignment, and assume that value will handle it \
369  * correcly */ \
370  this->value = value; \
371  return *this; \
372  } \
373  constexpr NAME##Value& operator=(T&& value) { \
374  /* Assume value handles self assigment correctly */ \
375  this->value = std::move(value); \
376  return *this; \
377  } \
378  template <typename U = T> \
379  constexpr NAME##Value& operator=(const NAME##Value<U>& other) { \
380  /* Assume value handles self assigment correctly */ \
381  value = *other; \
382  return *this; \
383  } \
384  template <typename U = T> \
385  constexpr NAME##Value& operator=(NAME##Value<U>&& other) { \
386  /* Assume value handles self assigment correctly */ \
387  value = *std::move(other); \
388  return *this; \
389  } \
390  constexpr const T& Get##NAME() const & { return value; } \
391  constexpr const T&& Get##NAME() const && { return std::move(value); } \
392  constexpr const T& Get() const & { return value; } \
393  constexpr const T&& Get() const && { return std::move(value); } \
394  template <typename U = T> \
395  constexpr const NAME##Value& Set##NAME(U&& value) { \
396  this->value = std::forward<U>(value); \
397  return *this; \
398  } \
399  template <typename U = T> \
400  constexpr const NAME##Value& Set(U&& value) { \
401  return Set##NAME(std::forward<U>(value)); \
402  } \
403  template <typename U = T> \
404  constexpr const NAME##Value& Set(const NAME##Value<U>& value) { \
405  return Set##NAME(*value); \
406  } \
407  template <typename U = T> \
408  constexpr const NAME##Value& Set(NAME##Value<U>&& value) { \
409  return Set##NAME(*std::move(value)); \
410  } \
411  constexpr T& operator*() & { return value; } \
412  constexpr T&& operator*() && { return std::move(value); } \
413  constexpr const T& operator*() const & { return value; } \
414  constexpr const T&& operator*() const && { return std::move(value); } \
415  template <typename M> \
416  constexpr auto Map(M&& map) & { \
417  return attribute_t::Make(std::forward<M>(value)); \
418  } \
419  template <typename M> \
420  constexpr auto Map(M&& map) const & { \
421  return attribute_t::Make(std::forward<M>(value)); \
422  } \
423  template <typename M> \
424  constexpr auto Map(M&& map) && { \
425  return attribute_t::Make(std::forward<M>(std::move(value))); \
426  } \
427  template <typename M> \
428  constexpr auto Map(M&& map) const && { \
429  return attribute_t::Make(std::forward<M>(std::move(value))); \
430  } \
431  }; \
432  template <typename T> \
433  constexpr const char* NAME##Value<T>::name; \
434  template <class A, class B> \
435  constexpr bool operator==(const NAME##Value<A>& a, \
436  const NAME##Value<B>& b) { \
437  return NAME::Get(a) == NAME::Get(b); \
438  } \
439  template <class T> \
440  std::ostream& operator<<(std::ostream& out, const NAME##Value<T>& value) { \
441  return out << #NAME "(" << value.Get() << ")"; \
442  }
443 
444  namespace __attrs_impl {
445 
446  template <class... T>
447  class AttrsParent : public T... {
448  protected:
449  struct args_tag {};
450  struct copy_tag {};
451  struct move_tag {};
452 
453  template <class U>
455  private:
456  template <class... X>
457  static copy_tag Detect(const Attrs<X...>&) {
458  return {};
459  };
460 
461  template <class... X>
462  static move_tag Detect(Attrs<X...>&&) {
463  return {};
464  };
465 
466  static args_tag Detect(...) { return {}; }
467 
468  public:
469  using type = decltype(Detect(std::declval<U>()));
470  };
471 
472  template <class U>
473  using constructor_detector =
474  typename __attrs_impl_constructor_detector<U>::type;
475 
476  constexpr AttrsParent() : T{}... {}
477 
478  template <class... U>
479  constexpr AttrsParent(const args_tag&, U&&... args)
480  : T{std::forward<U>(args)}... {}
481 
482  template <class... U>
483  constexpr AttrsParent(const copy_tag&, const Attrs<U...>& other)
484  : T{T::attribute_t::Get(other)}... {}
485 
486  template <class... U>
487  constexpr AttrsParent(const move_tag&, Attrs<U...>&& other)
488  : T{T::attribute_t::Get(std::move(other))}... {}
489  };
490 
491  // This struct exists so that we can pass around Attrs<U...> without it
492  // taking up any memory or having any side effects from construction.
493  template <class>
494  struct wrapper {};
495 
496  } // namespace __attrs_impl
497 
498  template <typename... T>
499  constexpr Attrs<std::decay_t<T>...> MakeAttrs(T&&... props);
500 
501  namespace __impl_attrs_reduce {
502  template <typename>
503  struct AttrsIter;
504 
505  template <>
506  struct AttrsIter<__impl_variadics_type_traits::pack<>> {
507  template <typename I, typename R, typename... A>
508  static constexpr I&& MergeReduce(I&& init, R&& reducer, A&&... attrs) {
509  return std::forward<I>(init);
510  }
511  template <typename I, typename R, typename... A>
512  static constexpr I&& Reduce(I&& init, R&& reducer, A&&... attrs) {
513  return std::forward<I>(init);
514  }
515 
516  template <typename F, typename... A>
517  static constexpr void MergeForeach(F&& callback, A&&... attrs) {}
518 
519  template <typename F, typename... A>
520  static constexpr void Foreach(F&& callback, A&&... attrs) {}
521  };
522 
523  template <typename U>
524  struct AttrsIter<__impl_variadics_type_traits::pack<U>> {
525  template <typename I, typename R, typename... A>
526  static constexpr auto MergeReduce(I&& init, R&& reducer, A&&... attrs) {
527  return std::forward<R>(reducer)(
528  std::forward<I>(init), U::attribute_t::GetAttributeOrGetAttributeIn(
529  std::forward<A>(attrs)...));
530  }
531  template <typename I, typename R, typename... A>
532  static constexpr auto Reduce(I&& init, R&& reducer, A&&... attrs) {
533  return std::forward<R>(reducer)(
534  std::forward<I>(init),
535  U::attribute_t::GetAttribute(std::forward<A>(attrs))...);
536  }
537  template <typename F, typename... A>
538  static constexpr void MergeForeach(F&& callback, A&&... attrs) {
539  std::forward<F>(callback)(
540  U::attribute_t::GetAttributeOrGetAttributeIn(
541  std::forward<A>(attrs)...));
542  }
543  template <typename F, typename... A>
544  static constexpr void Foreach(F&& callback, A&&... attrs) {
545  std::forward<F>(callback)(
546  U::attribute_t::GetAttribute(std::forward<A>(attrs))...);
547  }
548  };
549 
550  template <typename U0, typename U1, typename... U>
551  struct AttrsIter<__impl_variadics_type_traits::pack<U0, U1, U...>> {
552  template <typename I, typename R, typename... A>
553  static constexpr auto MergeReduce(I&& init, R&& reducer, A&&... attrs) {
554  using new_init_t =
555  decltype(reducer(std::forward<I>(init),
556  U0::attribute_t::GetAttributeOrGetAttributeIn(
557  std::forward<A>(attrs)...)));
558 
560  MergeReduce(std::forward<new_init_t>(
561  reducer(std::forward<I>(init),
562  U0::attribute_t::GetAttributeOrGetAttributeIn(
563  std::forward<A>(attrs)...))),
564  std::forward<R>(reducer), std::forward<A>(attrs)...);
565  }
566 
567  template <typename I, typename R, typename... A>
568  static constexpr auto Reduce(I&& init, R&& reducer, A&&... attrs) {
569  using new_init_t = decltype(
570  reducer(std::forward<I>(init),
571  U0::attribute_t::GetAttribute(std::forward<A>(attrs))...));
572 
574  Reduce(std::forward<new_init_t>(reducer(
575  std::forward<I>(init),
576  U0::attribute_t::GetAttribute(std::forward<A>(attrs))...)),
577  std::forward<R>(reducer), std::forward<A>(attrs)...);
578  }
579 
580  template <typename F, typename... A>
581  static constexpr void MergeForeach(F&& callback, A&&... attrs) {
582  callback(U0::attribute_t::GetAttributeOrGetAttributeIn(
583  std::forward<A>(attrs)...));
584 
586  MergeForeach(std::forward<F>(callback), std::forward<A>(attrs)...);
587  }
588 
589  template <typename F, typename... A>
590  static constexpr void Foreach(F&& callback, A&&... attrs) {
591  callback(U0::attribute_t::GetAttribute(std::forward<A>(attrs))...);
592 
594  Foreach(std::forward<F>(callback), std::forward<A>(attrs)...);
595  }
596  };
597 
598  } // namespace __impl_attrs_reduce
599 
600  template <typename I, typename R, typename... A>
601  constexpr auto MergeReduce(I&& init, R&& reducer, A&&... attrs) {
605  Attrs, typename std::decay_t<A>::attributes_t>...>>::
606  MergeReduce(std::forward<I>(init), std::forward<R>(reducer),
607  std::forward<A>(attrs)...);
608  }
609 
610  template <typename I, typename R, typename... A>
611  constexpr auto Reduce(I&& init, R&& reducer, A&&... attrs) {
615  Attrs, typename std::decay_t<A>::attributes_t>...>>::
616  Reduce(std::forward<I>(init), std::forward<R>(reducer),
617  std::forward<A>(attrs)...);
618  }
619 
620  template <typename F, typename... A>
621  constexpr void MergeForeach(F&& callback, A&&... attrs) {
625  Attrs, typename std::decay_t<A>::attributes_t>...>>::
626  MergeForeach(std::forward<F>(callback), std::forward<A>(attrs)...);
627  }
628  template <typename F, typename... A>
629  constexpr void Foreach(F&& callback, A&&... attrs) {
633  Attrs, typename std::decay_t<A>::attributes_t>...>>::
634  Foreach(std::forward<F>(callback), std::forward<A>(attrs)...);
635  }
636 
637  template <typename... T>
638  class Attrs : public __attrs_impl::AttrsParent<T...> {
639  public:
641  using pack_t = TypePack<T...>;
642 
643  constexpr Attrs() : __attrs_impl::AttrsParent<T...>{} {}
644 
645  // This is one of the really nasty parts. The problem is that we really
646  // want two constructors
647  //
648  // (1) template<class... U> Attrs(U&& ... MakeAttrs),
649  // which initializes all the members of the attribute pack and
650  //
651  // (2) template<class... U> Attrs(const Attrs<U...>& other),
652  // which copies the data out of the other attribute pack and into this
653  // one.
654  //
655  // Sadly, C++ can't tell the difference between these two signatures,
656  // and will only Call the first because of how c++ decides the order to
657  // resolve overloads in. In ordered to ensure that the correct
658  // constructor is called, we calculate which constructor should be
659  // called, and then pass the result into AttrsParent, which has
660  // unambiguously overloaded constructors which handle each case
661  template <class U0, class... U>
662  constexpr Attrs(U0&& arg, U&&... args)
664  // This will resolve to one of several marker structs which will
665  // select the correct constructor
666  typename __attrs_impl::AttrsParent<
667  T...>::template constructor_detector<U0>{},
668  // The arguments are then forwarded as normal
669  std::forward<U0>(arg), std::forward<U>(args)...) {}
670 
671  private:
672  constexpr static struct __impl_AssignOp_asssigner_t {
673  template <typename T1, typename T2>
674  constexpr void operator()(T1& to, T2&& from) const {
675  to = std::forward<T2>(from);
676  }
677  } __impl_AssignOp_asssigner{};
678 
679  public:
680  template <typename F>
681  Attrs& operator=(F&& from) {
682  emp::tools::Foreach(__impl_AssignOp_asssigner, *this,
683  std ::forward<F>(from));
684 
685  return *this;
686  }
687 
688  private:
689  template <bool Last, typename A>
690  struct GetAttr;
691  template <typename A>
692  struct GetAttr<false, A> {
693  template <typename S, typename... U>
694  static constexpr decltype(auto) Get(S&& Self, U&&... args) {
695  using attribute_t = typename A::attribute_t;
696  return attribute_t::CallOrGetAttribute(std::forward<S>(Self),
697  args...);
698  }
699  };
700 
701  template <typename A>
702  struct GetAttr<true, A> {
703  template <typename S, typename... U>
704  static constexpr decltype(auto) Get(S&& Self, U&&... args) {
705  using attribute_t = typename A::attribute_t;
706  return attribute_t::CallOrGetAttribute(std::forward<S>(Self),
707  std::forward<U>(args)...);
708  }
709  };
710 
711  template <typename S, typename... U>
712  static constexpr auto Call(S&& Self, U&&... args) {
713  constexpr size_t last = sizeof...(T) - 1;
714  return MakeAttrs(
715  GetAttr<variadic_index_of_v<T, Attrs> == last,
716  T>::template Get<S, U...>(std::forward<S>(Self),
717  std::forward<U>(args)...)...);
718  }
719 
720  public:
727  template <class... U>
728  constexpr auto operator()(U&&... args) & {
729  return Call(*this, std::forward<U>(args)...);
730  }
731 
732  template <class... U>
733  constexpr auto operator()(U&&... args) const & {
734  return Call(*this, std::forward<U>(args)...);
735  }
736 
737  template <class... U>
738  constexpr auto operator()(U&&... args) && {
739  return Call(std::move(*this), std::forward<U>(args)...);
740  }
741 
742  template <class... U>
743  constexpr auto operator()(U&&... args) const && {
744  return Call(std::move(*this), std::forward<U>(args)...);
745  }
746 
747  private:
748  struct eq_reducer {
749  template <typename A, typename B>
750  constexpr bool operator()(bool init, A&& a, B&& b) const {
751  return init && (std::forward<A>(a).Get() == std::forward<B>(b).Get());
752  }
753  };
754 
755  public:
759  template <class... U>
760  constexpr bool operator==(const Attrs<U...>& other) const {
761  // @todo: this needs more carefull checking, as it will have strange
762  // behavior when the other attribute pack has different types
763  return tools::Reduce(true, eq_reducer{}, *this, other);
764  }
765 
766  private:
767  template <typename F>
768  struct __impl_reduce_from_reduce_value {
769  F callback;
770  constexpr __impl_reduce_from_reduce_value(F callback)
771  : callback(std::forward<F>(callback)) {}
772  template <typename I, typename U>
773  constexpr auto operator()(I&& init, U&& value) {
774  return std::forward<F>(callback)(value.name, std::forward<I>(init),
775  *std::forward<U>(value));
776  }
777  };
778 
779  public:
780  template <typename I, typename F>
781  constexpr auto AttributeReduce(I&& init, F&& callback) & {
782  return emp::tools::Reduce(std::forward<I>(init),
783  std::forward<F>(callback), *this);
784  }
785  template <typename I, typename F>
786  constexpr auto AttributeReduce(I&& init, F&& callback) const & {
787  return emp::tools::Reduce(std::forward<I>(init),
788  std::forward<F>(callback), *this);
789  }
790  template <typename I, typename F>
791  constexpr auto AttributeReduce(I&& init, F&& callback) && {
792  return emp::tools::Reduce(std::forward<I>(init),
793  std::forward<F>(callback), std::move(*this));
794  }
795  template <typename I, typename F>
796  constexpr auto AttributeReduce(I&& init, F&& callback) const && {
797  return emp::tools::Reduce(std::forward<I>(init),
798  std::forward<F>(callback), std::move(*this));
799  }
800 
801  template <typename I, typename F>
802  constexpr auto Reduce(I&& init, F&& callback) {
803  return AttributeReduce(
804  std::forward<I>(init),
805  __impl_reduce_from_reduce_value<F&&>{std::forward<F>(callback)});
806  }
807  template <typename I, typename F>
808  constexpr auto Reduce(I&& init, F&& callback) const {
809  return AttributeReduce(
810  std::forward<I>(init),
811  __impl_reduce_from_reduce_value<F&&>{std::forward<F>(callback)});
812  }
813 
814  private:
815  template <typename F>
816  struct __impl_foreach_from_foreach_value {
817  F callback;
818  constexpr __impl_foreach_from_foreach_value(F callback)
819  : callback(std::forward<F>(callback)) {}
820  template <typename U>
821  constexpr void operator()(U&& value) {
822  std::forward<F>(callback)(value.name, *std::forward<U>(value));
823  }
824  };
825 
826  public:
827  template <typename F>
828  constexpr void AttributeForeach(F&& callback) & {
829  tools::Foreach(std::forward<F>(callback), *this);
830  }
831 
832  template <typename F>
833  constexpr void AttributeForeach(F&& callback) const & {
834  tools::Foreach(std::forward<F>(callback), *this);
835  }
836 
837  template <typename F>
838  constexpr void AttributeForeach(F&& callback) && {
839  tools::Foreach(std::forward<F>(callback), std::move(*this));
840  }
841 
842  template <typename F>
843  constexpr void AttributeForeach(F&& callback) const && {
844  tools::Foreach(std::forward<F>(callback), std::move(*this));
845  }
846 
847  template <typename F>
848  constexpr void Foreach(F&& callback) {
849  AttributeForeach(
850  __impl_foreach_from_foreach_value<decltype(
851  std::forward<F>(callback))>{std::forward<F>(callback)});
852  }
853 
854  template <typename F>
855  constexpr void Foreach(F&& callback) const {
856  AttributeForeach(
857  __impl_foreach_from_foreach_value<decltype(
858  std::forward<F>(callback))>{std::forward<F>(callback)});
859  }
860 
861  private:
862  template <typename S, typename U>
863  constexpr static Attrs<T..., std::decay_t<U>> __impl_SetAttribute(
864  const std::false_type& has_attr, S&& self, U&& attribute) {
865  return MakeAttrs(T::attribute_t::GetAttribute(std::forward<S>(self))...,
866  std::forward<U>(attribute));
867  }
868  template <typename S, typename U>
869  constexpr static auto __impl_SetAttribute(const std::true_type& has_attr,
870  S&& self, U&& attribute) {
871  return MakeAttrs(T::attribute_t::GetAttributeOrGetAttributeIn(
872  std::forward<S>(self), std::forward<U>(attribute))...);
873  }
874 
875  template <typename S, typename U>
876  constexpr static auto __impl_SetAttribute(S&& self, U&& attribute) {
877  return __impl_SetAttribute(
878  has_attribute<S, typename std::decay_t<U>::attribute_t>{},
879  std::forward<S>(self), std::forward<U>(attribute));
880  }
881 
882  public:
883  template <typename U>
884  constexpr auto SetAttribute(U&& attribute) & {
885  return __impl_SetAttribute(*this, std::forward<U>(attribute));
886  }
887 
888  template <typename U>
889  constexpr auto SetAttribute(U&& attribute) const & {
890  return __impl_SetAttribute(*this, std::forward<U>(attribute));
891  }
892 
893  template <typename U>
894  constexpr auto SetAttribute(U&& attribute) && {
895  return __impl_SetAttribute(std::move(*this),
896  std::forward<U>(attribute));
897  }
898 
899  template <typename U>
900  constexpr auto SetAttribute(U&& attribute) const && {
901  return __impl_SetAttribute(std::move(*this),
902  std::forward<U>(attribute));
903  }
904  };
905 
906  template <typename... T>
907  constexpr typename Attrs<T...>::__impl_AssignOp_asssigner_t
908  Attrs<T...>::__impl_AssignOp_asssigner;
909 
912  template <class... T>
913  constexpr Attrs<std::decay_t<T>...> MakeAttrs(T&&... props) {
914  return {std::forward<T>(props)...};
915  };
916 
917  namespace __impl_attrs_merge {
918  constexpr struct {
919  template <typename I, typename A>
920  constexpr auto operator()(I&& init, A&& next) const {
921  return std::forward<I>(init).SetAttribute(std::forward<A>(next));
922  }
923  } attrs_merge{};
924  } // namespace __impl_attrs_merge
925 
929  template <typename... U>
930  constexpr auto Merge(U&&... packs)
931  // This hint is required by some older compilers
933  std::forward<U>(packs)...)) {
935  std::forward<U>(packs)...);
936  }
937 
938  namespace __attrs_impl {
939  template <class...>
940  struct print_attrs_tag {};
941 
942  template <class... T, class H>
943  void PrintAttrs(std::ostream& out, const Attrs<T...>& attrs,
944  const print_attrs_tag<H>&) {
945  out << '"' << H::name << "\": " << H::attribute_t::Get(attrs);
946  }
947  template <class... T, class H0, class H1, class... U>
948  void PrintAttrs(std::ostream& out, const Attrs<T...>& attrs,
950  out << '"' << H0::name << "\": " << H0::attribute_t::Get(attrs) << ", ";
951  PrintAttrs(out, attrs, print_attrs_tag<H1, U...>{});
952  }
953  } // namespace __attrs_impl
954 
955  template <class H, class... T>
956  std::ostream& operator<<(std::ostream& out, const Attrs<H, T...>& attrs) {
957  out << "{ ";
958  __attrs_impl::PrintAttrs(out, attrs,
960  return out << " }";
961  }
962 
963  std::ostream& operator<<(std::ostream& out, const Attrs<>& attrs) {
964  return out << "{ }";
965  }
966  } // namespace tools
967 } // namespace emp
968 
969 #endif // EMP_PLOT_EMP
Definition: type_traits.h:100
constexpr bool is_attribute_value_v
Definition: attrs.h:26
constexpr auto operator()(U &&...args) const &&
Definition: attrs.h:743
constexpr T & operator()(value_t< T > &target) const
Definition: attrs.h:104
static constexpr void Foreach(F &&callback, A &&...attrs)
Definition: attrs.h:544
Definition: type_traits.h:91
constexpr auto operator()(U &&...args)&
Definition: attrs.h:728
constexpr auto AttributeReduce(I &&init, F &&callback) const &
Definition: attrs.h:786
decltype(HasAttr(std::declval< Pack >())) type
Definition: attrs.h:49
constexpr AttrsParent()
Definition: attrs.h:476
static constexpr auto MergeReduce(I &&init, R &&reducer, A &&...attrs)
Definition: attrs.h:553
constexpr bool has_attribute_v
Definition: attrs.h:56
constexpr auto SetAttribute(U &&attribute)&&
Definition: attrs.h:894
constexpr auto SetAttribute(U &&attribute)&
Definition: attrs.h:884
typename ToPack< Variadic, Pack >::type ToPackType
Definition: type_traits.h:116
constexpr void operator()(value_t< T > &target, V &&value) const
Definition: attrs.h:277
static constexpr void Foreach(F &&callback, A &&...attrs)
Definition: attrs.h:590
constexpr auto SetAttribute(U &&attribute) const &
Definition: attrs.h:889
typename __attrs_impl_constructor_detector< U >::type constructor_detector
Definition: attrs.h:474
void PrintAttrs(std::ostream &out, const Attrs< T... > &attrs, const print_attrs_tag< H0, H1, U... > &)
Definition: attrs.h:948
static constexpr I && Reduce(I &&init, R &&reducer, A &&...attrs)
Definition: attrs.h:512
constexpr auto operator()(U &&...args)&&
Definition: attrs.h:738
constexpr void Foreach(F &&callback)
Definition: attrs.h:848
constexpr auto operator()(U &&...args) const &
Definition: attrs.h:733
constexpr struct emp::tools::__impl_attrs_merge::@4 attrs_merge
constexpr void AttributeForeach(F &&callback) const &
Definition: attrs.h:833
Definition: attrs.h:24
constexpr void AttributeForeach(F &&callback)&
Definition: attrs.h:828
Definition: attrs.h:494
decltype(Detect(std::declval< U >())) type
Definition: attrs.h:469
constexpr auto Reduce(I &&init, F &&callback)
Definition: attrs.h:802
typename variadic_intersection< Cmp, U... >::type variadic_intersection_t
Definition: type_traits.h:397
constexpr auto Reduce(I &&init, F &&callback) const
Definition: attrs.h:808
A set of types that can be manipulated at compile time (good for metaprogramming) ...
constexpr auto MergeReduce(I &&init, R &&reducer, A &&...attrs)
Definition: attrs.h:601
static constexpr auto MergeReduce(I &&init, R &&reducer, A &&...attrs)
Definition: attrs.h:526
Definition: attrs.h:20
Value< T > value_t
Definition: attrs.h:63
typename variadic_union< Cmp, U... >::type variadic_union_t
Definition: type_traits.h:336
Definition: attrs.h:54
constexpr auto AttributeReduce(I &&init, F &&callback)&
Definition: attrs.h:781
static constexpr void MergeForeach(F &&callback, A &&...attrs)
Definition: attrs.h:581
static constexpr void MergeForeach(F &&callback, A &&...attrs)
Definition: attrs.h:517
constexpr const T && operator()(const value_t< T > &&target) const
Definition: attrs.h:114
static constexpr void Foreach(F &&callback, A &&...attrs)
Definition: attrs.h:520
std::ostream & operator<<(std::ostream &out, const Attrs< H, T... > &attrs)
Definition: attrs.h:956
constexpr AttrsParent(const args_tag &, U &&...args)
Definition: attrs.h:479
constexpr void Foreach(F &&callback, A &&...attrs)
Definition: attrs.h:629
Definition: attrs.h:17
constexpr void AttributeForeach(F &&callback) const &&
Definition: attrs.h:843
constexpr void Foreach(F &&callback) const
Definition: attrs.h:855
Definition: attrs.h:29
Attrs & operator=(F &&from)
Definition: attrs.h:681
constexpr auto Reduce(I &&init, R &&reducer, A &&...attrs)
Definition: attrs.h:611
constexpr auto AttributeReduce(I &&init, F &&callback)&&
Definition: attrs.h:791
constexpr void AttributeForeach(F &&callback)&&
Definition: attrs.h:838
If we are in emscripten, make sure to include the header.
Definition: array.h:37
static constexpr std::false_type HasAttr(...)
Definition: attrs.h:47
Definition: attrs.h:32
constexpr auto Merge(U &&...packs) -> decltype(MergeReduce(Attrs<>
Definition: attrs.h:930
static constexpr auto Reduce(I &&init, R &&reducer, A &&...attrs)
Definition: attrs.h:532
constexpr AttrsParent(const move_tag &, Attrs< U... > &&other)
Definition: attrs.h:487
static constexpr void MergeForeach(F &&callback, A &&...attrs)
Definition: attrs.h:538
constexpr auto SetAttribute(U &&attribute) const &&
Definition: attrs.h:900
constexpr const T & operator()(const value_t< T > &target) const
Definition: attrs.h:99
static constexpr I && MergeReduce(I &&init, R &&reducer, A &&...attrs)
Definition: attrs.h:508
void PrintAttrs(std::ostream &out, const Attrs< T... > &attrs, const print_attrs_tag< H > &)
Definition: attrs.h:943
constexpr value_t< std::decay_t< T > > operator()(T &&value) const
Definition: attrs.h:284
static constexpr auto Reduce(I &&init, R &&reducer, A &&...attrs)
Definition: attrs.h:568
Attr attribute_t
Definition: attrs.h:61
constexpr void MergeForeach(F &&callback, A &&...attrs)
Definition: attrs.h:621
constexpr T && operator()(value_t< T > &&target) const
Definition: attrs.h:109
constexpr Attrs< std::decay_t< T >... > MakeAttrs(T &&...props)
Definition: attrs.h:913
constexpr auto AttributeReduce(I &&init, F &&callback) const &&
Definition: attrs.h:796
constexpr AttrsParent(const copy_tag &, const Attrs< U... > &other)
Definition: attrs.h:483
static constexpr std::true_type HasAttr(const typename Attr::template value_t< T > &)
Definition: attrs.h:43
constexpr Attrs()
Definition: attrs.h:643
Extensions on the standard library type traits to handle Empirical classes (such as Ptr)...
Definition: TypePack.h:71
constexpr bool is_attributes_pack_v
Definition: attrs.h:37
constexpr bool operator==(const Attrs< U... > &other) const
Definition: attrs.h:760