type_traits.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2013 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef TILEDARRAY_TYPE_TRAITS_H__INCLUDED
21 #define TILEDARRAY_TYPE_TRAITS_H__INCLUDED
22 
23 /*
24  * N.B. this must be pure c++, usable without any context other than
25  * the current compiler + library + C++ standard.
26  * DO NOT include non-standard headers here!
27  */
28 #include <cassert>
29 #include <complex>
30 #include <functional>
31 #include <iterator>
32 #include <utility>
33 
34 #if __cplusplus <= 201703L
35 #include <boost/tuple/tuple.hpp>
36 #endif
37 
39 // implement C++17's type traits features if using CUDA with older C++ compiler
40 #if __cplusplus <= 201402L
41 
42 // GNU stdlibc++ provides void_t if -gnu++11 or -gnu++14 are given
43 #if __GNUC__ && defined(__GLIBCXX__) && !__STRICT_ANSI__ && \
44  __cplusplus >= 201103L
45 #define HAVE_VOID_T
46 #endif
47 
48 #ifndef HAVE_VOID_T // implement void_t if needed
49 namespace std {
50 template <typename... Ts>
51 struct make_void {
52  using type = void;
53 };
54 template <typename... Ts>
55 using void_t = typename make_void<Ts...>::type;
56 } // namespace std
57 #endif
58 
59 namespace std {
60 template <class T>
61 inline constexpr bool is_integral_v = is_integral<T>::value;
62 }
63 #endif // C++14 only
64 
66 // forward declarations
67 
68 namespace madness {
69 
70 template <typename T>
71 class Future;
72 
73 } // namespace madness
74 
75 namespace TiledArray {
76 template <typename>
77 class Tile;
78 class DensePolicy;
79 struct ZeroTensor;
80 template <typename, typename>
81 class DistArray;
82 namespace detail {
83 template <typename, typename>
84 class LazyArrayTile;
85 } // namespace detail
86 } // namespace TiledArray
87 
89 // see https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector
90 
94 #define GENERATE_HAS_MEMBER(Member) \
95  template <typename T, typename Enabler = void> \
96  class __has_member_##Member : public std::false_type {}; \
97  template <typename T> \
98  class __has_member_##Member< \
99  T, typename std::enable_if<std::is_class<T>::value || \
100  std::is_union<T>::value>::type> { \
101  using Yes = char[2]; \
102  using No = char[1]; \
103  \
104  struct Fallback { \
105  int Member; \
106  }; \
107  struct Derived : T, Fallback {}; \
108  \
109  template <class U> \
110  static No& test(decltype(U::Member)*); \
111  template <typename U> \
112  static Yes& test(U*); \
113  \
114  public: \
115  static constexpr bool value = \
116  sizeof(test<Derived>(nullptr)) == sizeof(Yes); \
117  }; \
118  \
119  template <class T> \
120  struct has_member_##Member \
121  : public std::integral_constant<bool, __has_member_##Member<T>::value> { \
122  };
123 
127 #define GENERATE_HAS_MEMBER_TYPE(Type) \
128  template <typename T, typename Enabler = void> \
129  class __has_member_type_##Type : public std::false_type {}; \
130  template <typename T> \
131  class __has_member_type_##Type< \
132  T, typename std::enable_if<std::is_class<T>::value || \
133  std::is_union<T>::value>::type> { \
134  using Yes = char[2]; \
135  using No = char[1]; \
136  \
137  struct Fallback { \
138  struct Type {}; \
139  }; \
140  struct Derived : T, Fallback {}; \
141  \
142  template <class U> \
143  static No& test(typename U::Type*); \
144  template <typename U> \
145  static Yes& test(U*); \
146  \
147  public: \
148  static constexpr bool value = \
149  sizeof(test<Derived>(nullptr)) == sizeof(Yes); \
150  }; \
151  \
152  template <class T> \
153  struct has_member_type_##Type \
154  : public std::integral_constant<bool, \
155  __has_member_type_##Type<T>::value> {}; \
156  \
157  template <class T> \
158  constexpr const bool has_member_type_##Type##_v = \
159  has_member_type_##Type<T>::value;
160 
169 #define GENERATE_HAS_MEMBER_FUNCTION(Member) \
170  template <typename T, typename Result, typename... Args> \
171  class __has_member_function_##Member { \
172  using Yes = char; \
173  using No = int; \
174  template <typename U, Result (U::*)(Args...)> \
175  struct Check; \
176  template <typename U, Result (U::*)(Args...) const> \
177  struct CheckConst; \
178  template <typename U> \
179  static Yes test_const(CheckConst<U, &U::Member>*); \
180  template <typename U> \
181  static No test_const(...); \
182  template <typename U> \
183  static Yes test_nonconst(Check<U, &U::Member>*); \
184  template <typename U> \
185  static No test_nonconst(...); \
186  \
187  public: \
188  static constexpr const bool value = \
189  sizeof(test_const<T>(0)) == sizeof(Yes) || \
190  (!std::is_const<T>::value ? sizeof(test_nonconst<T>(0)) == sizeof(Yes) \
191  : false); \
192  }; \
193  template <class T, typename Result, typename... Args> \
194  struct has_member_function_##Member \
195  : public std::integral_constant< \
196  bool, __has_member_function_##Member<T, Result, Args...>::value> { \
197  }; \
198  \
199  template <class T, typename Result, typename... Args> \
200  constexpr const bool has_member_function_##Member##_v = \
201  has_member_function_##Member<T, Result, Args...>::value;
202 
211 #define GENERATE_HAS_MEMBER_FUNCTION_ANYRETURN(Member) \
212  template <typename T, typename... Args> \
213  class __has_member_function_##Member##_anyreturn { \
214  using Yes = char; \
215  using No = int; \
216  template <typename U, typename... Args_> \
217  static auto func(void*) \
218  -> decltype(std::add_pointer_t<decltype(std::declval<U>().Member( \
219  std::declval<Args_>()...))>{}, \
220  Yes{}); \
221  template <typename U, typename... Args_> \
222  static No func(...); \
223  \
224  public: \
225  static constexpr const bool value = \
226  sizeof(func<T, Args...>(0)) == sizeof(Yes); \
227  }; \
228  template <class T, typename... Args> \
229  struct has_member_function_##Member##_anyreturn \
230  : public std::integral_constant< \
231  bool, \
232  __has_member_function_##Member##_anyreturn<T, Args...>::value> {}; \
233  \
234  template <class T, typename... Args> \
235  constexpr const bool has_member_function_##Member##_anyreturn_v = \
236  has_member_function_##Member##_anyreturn<T, Args...>::value;
237 
244 #define GENERATE_IS_FREE_FUNCTION_ANYRETURN(Function) \
245  template <typename... Args> \
246  class __is_free_function_##Function##_anyreturn { \
247  using Yes = char; \
248  using No = int; \
249  template <typename... Args_> \
250  static auto func(void*) -> decltype( \
251  std::add_pointer_t<decltype(Function(std::declval<Args_>()...))>{}, \
252  Yes{}); \
253  template <typename...> \
254  static No func(...); \
255  \
256  public: \
257  static constexpr const bool value = \
258  sizeof(func<Args...>(0)) == sizeof(Yes); \
259  }; \
260  template <typename... Args> \
261  struct is_free_function_##Function##_anyreturn \
262  : public std::integral_constant< \
263  bool, __is_free_function_##Function##_anyreturn<Args...>::value> { \
264  }; \
265  \
266  template <typename... Args> \
267  constexpr const bool is_free_function_##Function##_anyreturn_v = \
268  is_free_function_##Function##_anyreturn<Args...>::value;
269 
273 #define GENERATE_IS_FREE_FUNCTION_STD_ANYRETURN(Function) \
274  template <typename... Args> \
275  class __is_free_function_std_##Function##_anyreturn { \
276  using Yes = char; \
277  using No = int; \
278  template <typename... Args_> \
279  static auto func(void*) \
280  -> decltype(std::add_pointer_t<decltype( \
281  ::std::Function(std::declval<Args_>()...))>{}, \
282  Yes{}); \
283  template <typename...> \
284  static No func(...); \
285  \
286  public: \
287  static constexpr const bool value = \
288  sizeof(func<Args...>(0)) == sizeof(Yes); \
289  }; \
290  template <typename... Args> \
291  struct is_free_function_std_##Function##_anyreturn \
292  : public std::integral_constant< \
293  bool, \
294  __is_free_function_std_##Function##_anyreturn<Args...>::value> {}; \
295  \
296  template <typename... Args> \
297  constexpr const bool is_free_function_std_##Function##_anyreturn_v = \
298  is_free_function_std_##Function##_anyreturn<Args...>::value;
299 
300 namespace TiledArray {
301 namespace detail {
302 
304 // standard container traits (incomplete)
305 
306 GENERATE_HAS_MEMBER_TYPE(value_type)
307 GENERATE_HAS_MEMBER_TYPE(allocator_type)
308 GENERATE_HAS_MEMBER_TYPE(size_type)
309 GENERATE_HAS_MEMBER_TYPE(difference_type)
310 GENERATE_HAS_MEMBER_TYPE(reference)
311 GENERATE_HAS_MEMBER_TYPE(const_reference)
313 GENERATE_HAS_MEMBER_TYPE(const_pointer)
314 GENERATE_HAS_MEMBER_TYPE(iterator)
315 GENERATE_HAS_MEMBER_TYPE(const_iterator)
316 GENERATE_HAS_MEMBER_TYPE(reverse_iterator)
317 GENERATE_HAS_MEMBER_TYPE(const_reverse_iterator)
318 GENERATE_HAS_MEMBER_TYPE(key_type)
319 GENERATE_HAS_MEMBER_TYPE(mapped_type)
320 
330 
347 
348 // standard iterator traits
350 // GENERATE_HAS_MEMBER_TYPE(value_type)
351 // GENERATE_HAS_MEMBER_TYPE(difference_type)
352 // GENERATE_HAS_MEMBER_TYPE(reference)
353 // GENERATE_HAS_MEMBER_TYPE(pointer)
354 GENERATE_HAS_MEMBER_TYPE(iterator_category)
355 
356 // these are useful to detect presence of overloads
360 
361 
377 
379 
380 } // namespace detail
381 } // namespace TiledArray
382 
383 namespace TiledArray {
384 namespace detail {
388 template <typename>
389 struct is_type : public std::true_type {};
392 template <typename T>
393 constexpr const bool is_type_v = is_type<T>::value;
394 
400 template <typename T, typename = void>
401 struct is_complete_type : std::false_type {};
402 
403 template <>
404 struct is_complete_type<void> : std::false_type {};
405 
406 template <typename T>
407 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
408 
411 template <typename T>
413 
414 } // namespace detail
415 } // namespace TiledArray
416 
417 namespace TiledArray {
418 
424 template <typename>
425 struct eval_trait;
426 
427 namespace detail {
428 
429 GENERATE_HAS_MEMBER_TYPE(eval_type)
430 
431 #if !defined(__INTEL_COMPILER_BUILD_DATE)
438 template <typename From, typename To, typename Enabler = void>
439 struct has_conversion_operator : std::false_type {};
440 
441 template <typename From, typename To>
443  From, To,
444  typename std::enable_if<
445  is_type<decltype(std::declval<From>().operator To())>::value>::type>
446  : std::true_type {};
447 
448 template <typename From, typename To>
450  From, To,
451  typename std::enable_if<
452  is_type<decltype(std::declval<From>().operator To&())>::value>::type>
453  : std::true_type {};
454 #else
455 template <typename From, typename To>
457  /*
458  * see
459  * https://stackoverflow.com/questions/87372/check-if-a-class-has-a-member-function-of-a-given-signature#answer-10707822
460  * this works for icc and all other compilers tested:
461  * <iframe width="800px" height="200px"
462  * src="https://godbolt.org/e?readOnly=true&hideEditorToolbars=true#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAM1QDsCBlZAQwBtMQBGAFlICsQAJlKtmtUMgCkggELSZpAM6Z2yAnjqVMtdAGFUrAK4BbWl1Lb0AGTy1MAORMAjTMRDcArKQAOqRYQ1afSNTc19/dTobO0djFzdPJRVMNUCGAmZiAmCTM04k1UjadMyCaIdnV3cvRQysnND82tLy2PjqgEolVENiZA4AcmkAZltkIywAaklh3UN1VkIATxnsSQAGAEENzYJMY29RPenZgiXvbWZjTEmAMWJUY1JJs4vaK5uAFVRVnfHmRSKSYIAEAfTQtAAbq5/HRQagLsRmERiDtJAB2ORbSY4l7nTBYKiTZAg4iTOiYGZYza4ya1YiGNQvADuqGmmOJpMmAA9JB4ZII%2BQARKnskXDak7Wl7A5HG4zXSvS7XO7PJXvFWfNX4jXy4ZCukEdAgECXJzsUF4KigggK2rGkB4RTg0SAhVYcZKiD2k0e1iQtgKiG1O7SABsqwgHQAdAjXMiSJNPlGOqsTQGjJThmts4bkXhkOS7C9MLUIJM/V6fSA/Rmg3QQ7dw5GY3GkSikymAFSTVMSqW4mWHZF6xU6j6qvFvCefVZ59SFgisktl6NrvuSrbeQzmgsgAc47QmdkySYZwx6g3%2BABemFQVAge1qCvuj2e30j6w6HRO4qveFve8IBJTIfwxcVJXRCC0S2EYxgmUclRtJFCEUX5YK2AB6LswDAJMEBuIc5WmMN1hBZ1gwIUFiEwKhXG0fp4W8BUtRzNZSMmTBuV8LIgWYA9JicVADEwMRiQbDJ6BI9Zz0IkECEmJ0XgZG4rSJSRSNnDjvAeSE8CwNDsVxDT1mwJMTTbBNiC7KNxNoZ9SJ2LtMOmLYiJHBUp2VG5XyeLzdSTH5sx2elGQU8jwToaFiFhWgmPjFFBVgzEBOwyYGFuABJexNjMyyUQAWnIgq0GIGi1AK/xgEmEAf2cgT3L2BV1QnbZgqMnFmgXQ0HQIFSbXxFcCAgb5JggTYTS7DpbMosCUo62lJhogheloHqTT6i8BouKMqQE8CYJpXE0oy7LcvJRErIKrinQIIFasmeqFsaxDxxVNqzIErqCwrFJWC9J9hvDCaQHyxNvm/VyjpxQGIErfEIGBizLo7CHSEhVB9MeubqUW46ewAeRRxMbtqRRo0mAB1eTJmYIT5jpPBgBmW5HswgTpXxQlfs9BHYaR0HibJCGf2W1btqzU8OdxMXiDW2W4q9Dd9qgw7aROrKcrM4AJ1QaKavLJ7oZLWUPNON6bg%2Br6Mm66sqDYZQJaGiA12jHHpZxBX1pAe3WEdpXRRVkUMONtLPgQJTmTwVhWEEm5MEIAiyRM6tNswCWTPJZPSLth306VTOjc5i5ufhnbAZfB5jE/Ugvx/Av%2BxD2lvsLSjBOE2PZN/Lz0zYC9RTS6mCwQRSgUIFm2bRVXG82UKmU%2BdYTwOme54Uz5OCX6fqVXu4l6MrjDgLQgLoS8H1hmiSTyWzAVrlzeILFKfoJDuCqG50FQWyz5sCsUFdAJgAsgABUylYbAAAlUEMgACqoChSgiFJsb%2BaJBDDGZJkWgthqrSEEJlXQugKyoFLJMWgqAFKsmIAAa0mFHAgI86E3CoHgGKCloqxXJESBhylmDj0EElbYqCVDKBCjbAsoIATKCyBACKEI2GBHiu2EgL53zrDTCAWSzwcE9BJKovhytYKCJ0FaER%2BZkDiMBK4YauEZFRRhPIsGqJZi3HfJwNRGjph8O0QgVxei9pbBbuYyRw0bFQjsXCBxgonEqLcX3TAmjPGMgQLowQ%2BjZ6iLMRIyxEBrFglkWEuKETlFJlcdmXumZ4mCC8T4lJVIBhdFYCAAYHgBikDMAMdYLTUCNN0PIeQdIeh9HlKgwQLSCCNI6d%2BUglD3DrGjMMYYHhOCCAABxhjDB4bgYYACc6JlkiEadwFpbSOmkC6QMFpigQDrFIGM9pdTSBwFgEgNABxo6uHIJQF53g3luALMgTgWz8hMP%2BjCSgThxktKcLYTISxGmcBaS8649ACa0FYLCu5pAsDGDEMAdgELMXMJSOoaElyMVcRSPMQY8LyD0BUPixYTgkTECWPoLAcLRnEDwMYdlXQaD0CYGwDgPB%2BDmFEOIFAvTZAiDwE4S5kAugIiKKSyqRoZhCikLIeQPALnJFSJoCAlgGh5AsDoVolQ3D5HCAEOgRqwh%2BGtbQM1cQqhNF1UUEo9QDC5HMMoQoaQ6hlFsBUZ1FqlABttU0ANTr2icC6IoAZ/QhD1Mac01p%2BKznclWQVMM3BFLIELAC6MsyN4QFwIQRMIxhCTH0K89gydUGxurZKmQoyIWTIIswLAbgoxTKEIIOZ3BuDDHRJ4dYHhlnrEEFs5ZwgGkDEOWmjFZyLlXJuW2h5MBECg3mNuAgHzgKPG%2BXW8wBJy1uGEHyxgLA8XCuZEibwPL9lNKOemxpIwN60JHpmsM2bc1/MmIW4tra7mTOmcOuZgh1jcC2WGGdyz0SCAQ7wOdC7jmdMaSu65tyJnJoGCMxdJzl1rpA10ORmhuBAA"></iframe>
463  */
464 
465  /* operator has correct sig */
466  template <typename A>
467  static std::true_type test(To (A::*)() const) {
468  return std::true_type();
469  }
470 
471  /* operator exists */
472  template <typename A>
473  static decltype(test(&A::operator To)) test(decltype(&A::operator To),
474  void*) {
475  /* Operator exists. What about sig? */
476  typedef decltype(test(&A::operator To)) return_type;
477  return return_type();
478  }
479 
480  /* operator does not exist */
481  template <typename A>
482  static std::false_type test(...) {
483  return std::false_type();
484  }
485 
486  /* This will be either `std::true_type` or `std::false_type` */
487  typedef decltype(test<From>(0, 0)) type;
488 
489  static const bool value = type::value; /* Which is it? */
490 };
491 #endif
492 
495 template <class From, class To>
496 constexpr const bool has_conversion_operator_v =
498 
502 template <class From, class To>
503 struct is_explicitly_convertible : public std::is_constructible<To, From> {};
504 
507 template <class From, class To>
508 constexpr const bool is_explicitly_convertible_v =
510 
515 template <class From, class To>
516 struct is_implicitly_convertible : public std::is_convertible<From, To> {};
517 
520 template <class From, class To>
521 constexpr const bool is_implicitly_convertible_v =
523 
528 template <class From, class To>
530  : public std::integral_constant<
531  bool, is_implicitly_convertible<From, To>::value ||
532  is_explicitly_convertible<From, To>::value> {};
533 
536 template <class From, class To>
538 
539 template <typename T, typename Enabler = void>
541  typedef T type;
542  static constexpr bool is_consumable = false;
543  static constexpr bool nonblocking = false;
544 }; // struct eval_trait
545 
546 template <typename T>
548  T,
549  typename std::enable_if<
550  has_member_type_eval_type<T>::value &&
551  (detail::is_explicitly_convertible<T, typename T::eval_type>::value ||
552  detail::is_explicitly_convertible<
553  T, madness::Future<typename T::eval_type>>::value ||
554  detail::is_implicitly_convertible<T, typename T::eval_type>::value ||
555  detail::is_implicitly_convertible<
556  T, madness::Future<typename T::eval_type>>::value)>::type> {
557  typedef typename T::eval_type type;
558  static constexpr bool is_consumable = false;
559  static constexpr bool nonblocking =
564 }; // struct eval_trait
565 
566 } // namespace detail
567 
569 
579 template <typename T>
581 
583 
588 template <typename T>
590  : public std::integral_constant<
591  bool, !std::is_same<T, typename eval_trait<T>::type>::value> {};
592 
593 template <typename Tile, typename Policy>
594 struct is_lazy_tile<DistArray<Tile, Policy>> : public std::false_type {};
595 
597 template <typename T>
598 constexpr const bool is_lazy_tile_v = is_lazy_tile<T>::value;
599 
601 
609 template <typename T>
611  : public std::integral_constant<bool, !is_lazy_tile<T>::value> {};
612 
613 template <>
614 struct is_consumable_tile<ZeroTensor> : public std::false_type {};
615 
617 template <typename T>
619 
622 namespace detail {
623 
624 template <typename T>
625 struct is_complex : public std::false_type {};
626 
627 template <typename T>
628 struct is_complex<std::complex<T>> : public std::true_type {};
629 
631 template <typename T>
632 constexpr const bool is_complex_v = is_complex<T>::value;
633 
634 template <typename T>
635 struct is_numeric : public std::is_arithmetic<T> {};
636 
637 template <typename T>
638 struct is_numeric<std::complex<T>> : public is_numeric<T> {};
639 
640 template <>
641 struct is_numeric<bool> : public std::false_type {};
642 
644 template <typename T>
645 constexpr const bool is_numeric_v = is_numeric<T>::value;
646 
648 template <typename T, typename U = void>
649 using enable_if_numeric_t = std::enable_if_t<is_numeric_v<T>, U>;
650 
651 template <typename T>
652 struct is_scalar : public is_numeric<T> {};
653 
654 template <typename T>
655 struct is_scalar<std::complex<T>> : public std::false_type {};
656 
658 template <typename T>
659 constexpr const bool is_scalar_v = is_scalar<T>::value;
660 
662 
668 // \tparam T The tile type to test
669 template <typename T>
670 struct is_array_tile : public std::false_type {};
671 
672 template <typename T, typename Op>
674  : public std::true_type {}; // struct is_array_tile
675 
677 template <typename T>
679 
681 
687 template <typename T>
689  : public std::integral_constant<bool, is_lazy_tile<T>::value &&
690  (!is_array_tile<T>::value)> {
691 }; // struct is_non_array_lazy_tile
692 
695 template <typename T>
696 constexpr const bool is_non_array_lazy_tile_v =
698 
700 
708 template <typename T, typename Enabler = void>
710 
711 template <typename T>
712 struct numeric_type<T, typename std::enable_if<is_numeric_v<T>>::type> {
713  typedef T type;
714 };
715 
716 template <typename T>
718  T, typename std::enable_if<has_member_type_value_type<T>::value &&
719  (!is_lazy_tile<T>::value) &&
720  (!is_numeric_v<T>)>::type>
721  : public numeric_type<typename T::value_type> {};
722 
723 template <typename T>
724 struct numeric_type<T, typename std::enable_if<is_lazy_tile<T>::value &&
725  !is_numeric_v<T>>::type>
726  : public numeric_type<typename eval_trait<T>::type> {};
727 
729 template <typename T>
731 
733 
743 template <typename T, typename Enabler = void>
744 struct scalar_type;
745 
746 template <typename T>
747 struct scalar_type<T, typename std::enable_if<is_scalar_v<T>>::type> {
748  typedef T type;
749 };
750 
751 template <typename T>
752 struct scalar_type<std::complex<T>, void> : public scalar_type<T> {};
753 
754 template <typename T>
755 struct scalar_type<T, typename std::enable_if<!is_numeric_v<T>>::type>
756  : public scalar_type<typename numeric_type<T>::type> {};
757 
759 template <typename T>
761 
762 template <typename T>
764  using Yes = char;
765  using No = int;
766  template <typename U>
767  static auto test(void*) -> decltype(
768  std::add_pointer_t<decltype(std::declval<U>() < std::declval<U>())>{},
769  Yes{});
770  template <typename...>
771  static No test(...);
772 
773  public:
774  static constexpr const bool value = sizeof(test<T>(0)) == sizeof(Yes);
775 };
776 
779 template <typename T>
781  : public std::integral_constant<bool,
783 
785 template <typename T>
787 
788 template <typename...>
790 
791 template <typename T, typename... Ts>
792 struct is_integral_list_helper<T, Ts...> {
793  static constexpr bool value =
794  std::is_integral<T>::value && is_integral_list_helper<Ts...>::value;
795 };
796 
797 template <>
799  static constexpr bool value = true;
800 };
801 
805 template <typename... Ts>
807  : std::conditional<(sizeof...(Ts) > 0ul), is_integral_list_helper<Ts...>,
808  std::false_type>::type {};
809 
811 template <typename... Ts>
812 constexpr const bool is_integral_list_v = is_integral_list<Ts...>::value;
813 
815 
818 template <class T>
819 struct is_tuple : std::false_type {};
820 
821 template <typename... Ts>
822 struct is_tuple<std::tuple<Ts...>> : std::true_type {};
823 
825 template <typename T>
826 constexpr const bool is_tuple_v = is_tuple<T>::value;
827 
829 
830 #if __cplusplus <= 201703L
831 template <std::size_t I, typename T, typename = void>
832 struct is_std_gettable : std::false_type {};
833 
834 template <std::size_t I, typename T>
836  I, T, std::void_t<decltype(::std::get<I>(std::declval<const T&>()))>>
837  : std::true_type {};
838 
839 template <std::size_t I, typename T>
841 
842 template <std::size_t I, typename T, typename = void>
843 struct is_boost_gettable : std::false_type {};
844 
845 template <std::size_t I, typename T>
847  I, T, std::void_t<decltype(::boost::get<I>(std::declval<const T&>()))>>
848  : std::true_type {};
849 
850 template <std::size_t I, typename T>
852 
853 template <std::size_t I, typename T>
854 constexpr const bool is_gettable_v =
855  is_std_gettable_v<I, T> || is_boost_gettable_v<I, T>;
856 
857 template <std::size_t I, typename T>
858 auto get(T&& t) {
859  using boost::get;
860  using std::get;
861  return get<I>(std::forward<T>(t));
862 }
863 #else // C++20
864 template <std::size_t I, typename T, typename = void>
865 struct is_gettable : std::false_type {};
866 
867 template <std::size_t I, typename T>
868 struct is_gettable<I, T, std::void_t<decltype(get<I>(std::declval<T>()))>>
869  : std::true_type {};
870 
871 template <std::size_t I, typename T>
872 constexpr const bool is_gettable_v = is_gettable<I, T>::value;
873 #endif
874 
878 template <class T, typename Enabler = void>
879 struct is_gettable_pair : std::false_type {};
880 
881 template <typename T>
883  T, std::enable_if_t<is_gettable_v<0, T> && is_gettable_v<1, T>>>
884  : std::true_type {};
885 
887 template <typename T>
889 
891 
892 template <class T, class = void>
893 struct is_integral_pair_ : std::false_type {};
894 template <class T1, class T2>
896  std::pair<T1, T2>,
897  typename std::enable_if<std::is_integral<T1>::value &&
898  std::is_integral<T2>::value>::type>
899  : std::true_type {};
904 template <class T>
906 
908 template <typename T>
910 
912 
913 template <typename...>
915 
916 template <typename T, typename... Ts>
918  static constexpr bool value =
920 };
921 
922 template <>
924  static constexpr bool value = true;
925 };
926 
930 template <typename... Ts>
932  : std::conditional<(sizeof...(Ts) > 0ul),
934  std::false_type>::type {};
935 
938 template <typename... Ts>
939 constexpr const bool is_integral_pair_list_v =
940  is_integral_pair_list<Ts...>::value;
941 
945 template <typename T>
946 struct is_integral_tuple : std::false_type {};
947 template <typename... Ts>
948 struct is_integral_tuple<std::tuple<Ts...>> : is_integral_list<Ts...> {};
949 
951 template <typename T>
953 
955 template <typename T>
956 struct remove_cvr {
957  typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type
959 };
960 
961 template <typename T>
963 
965 template <bool B, typename T>
966 using const_if_t = typename std::conditional<B, const T, T>::type;
967 
968 template <typename T, typename Enabler = void>
969 struct param {
970  typedef
971  typename std::add_lvalue_reference<typename std::add_const<T>::type>::type
973 };
974 
975 template <typename T>
976 struct param<T, typename std::enable_if<is_numeric_v<T>>::type> {
977  typedef typename std::add_const<T>::type type;
978 };
979 
980 template <typename T>
981 struct param<T, typename std::enable_if<std::is_reference<T>::value>::type> {
982  typedef T type;
983 };
984 
985 template <typename T>
986 struct param<T, typename std::enable_if<std::is_pointer<T>::value>::type> {
987  typedef typename std::add_const<T>::type type;
988 };
989 
990 template <typename U>
991 using param_type = typename param<U>::type;
992 
994 
995 template <typename T, typename Enabler = void>
996 struct is_iterator : public std::false_type {
998 };
999 
1000 template <typename T>
1001 struct is_iterator<T, typename std::enable_if<
1002  has_member_type_iterator_category<T>::value>::type>
1003  : public std::true_type {
1004  typedef typename std::iterator_traits<T>::iterator_category iterator_category;
1005 };
1006 
1007 template <typename T>
1008 struct is_iterator<T*, void> : std::true_type {
1009  typedef std::random_access_iterator_tag iterator_category;
1010 };
1011 
1012 template <typename T>
1013 struct is_iterator<const T*, void> : std::true_type {
1014  typedef std::random_access_iterator_tag iterator_category;
1015 };
1016 
1017 template <typename T>
1018 struct is_iterator<T* const, void> : std::true_type {
1019  typedef std::random_access_iterator_tag iterator_category;
1020 };
1021 
1022 template <typename T>
1023 struct is_iterator<const T* const, void> : std::true_type {
1024  typedef std::random_access_iterator_tag iterator_category;
1025 };
1026 
1027 template <typename T>
1029  : public std::is_base_of<std::input_iterator_tag,
1030  typename is_iterator<T>::iterator_category> {};
1031 
1032 template <typename T>
1034  : public std::is_base_of<std::output_iterator_tag,
1035  typename is_iterator<T>::iterator_category> {};
1036 
1037 template <typename T>
1039  : public std::is_base_of<std::forward_iterator_tag,
1040  typename is_iterator<T>::iterator_category> {};
1041 
1042 template <typename T>
1044  : public std::is_base_of<std::bidirectional_iterator_tag,
1045  typename is_iterator<T>::iterator_category> {};
1046 
1047 template <typename T>
1049  : public std::is_base_of<std::random_access_iterator_tag,
1050  typename is_iterator<T>::iterator_category> {};
1051 
1053 
1058 template <typename T, typename Enabler = void>
1059 struct is_range : std::false_type {};
1060 
1061 template <typename T>
1062 struct is_range<T, std::void_t<decltype(std::begin(std::declval<T&>()),
1063  std::end(std::declval<T&>()))>>
1064  : std::true_type {};
1065 
1067 template <typename T>
1068 static constexpr bool is_range_v = is_range<T>::value;
1069 
1074 template <typename T, typename Enabler = void>
1075 struct is_sized_range : std::false_type {};
1076 
1077 template <typename T>
1078 struct is_sized_range<T, std::void_t<decltype(std::size(std::declval<T&>()))>>
1079  : is_range<T> {};
1080 
1082 template <typename T>
1083 static constexpr bool is_sized_range_v = is_sized_range<T>::value;
1084 
1089 template <typename T, typename Enabler = void>
1090 struct is_contiguous_range : std::false_type {};
1091 
1092 template <typename T>
1094  std::void_t<decltype(std::data(std::declval<T&>()))>>
1095  : is_range<T> {};
1096 
1098 template <typename T>
1099 static constexpr bool is_contiguous_range_v = is_contiguous_range<T>::value;
1100 
1105 template <class T>
1106 using iterator_t = decltype(std::begin(std::declval<T&>()));
1107 
1112 template <class T>
1114 
1118 template <typename T, typename Enabler = void>
1119 struct is_integral_range : std::false_type {};
1120 
1121 template <typename T>
1123  T, std::enable_if_t<std::is_integral_v<value_t<T>> && is_range_v<T>>>
1124  : std::true_type {};
1125 
1127 template <typename T>
1128 static constexpr bool is_integral_range_v = is_integral_range<T>::value;
1129 
1133 template <typename T, typename Enabler = void>
1134 struct is_integral_sized_range : std::false_type {};
1135 
1136 template <typename T>
1138  T, std::enable_if_t<std::is_integral_v<value_t<T>> && is_sized_range_v<T>>>
1139  : std::true_type {};
1140 
1143 template <typename T>
1144 static constexpr bool is_integral_sized_range_v =
1146 
1148 
1149 // Type traits used to determine the result of arithmetic operations between
1150 // two types.
1151 
1152 template <typename Scalar1, typename Scalar2>
1153 using add_t = decltype(std::declval<Scalar1>() + std::declval<Scalar2>());
1154 
1155 template <typename Scalar1, typename Scalar2>
1156 using subt_t = decltype(std::declval<Scalar1>() - std::declval<Scalar2>());
1157 
1158 template <typename Scalar1, typename Scalar2>
1159 using mult_t = decltype(std::declval<Scalar1>() * std::declval<Scalar2>());
1160 
1161 template <typename T>
1162 struct is_array : public std::false_type {};
1163 
1164 template <typename T, typename P>
1165 struct is_array<DistArray<T, P>> : public std::true_type {};
1166 
1167 template <typename T>
1168 static constexpr bool is_array_v = is_array<T>::value;
1169 
1170 template <typename T>
1171 using trange_t = typename T::trange_type;
1172 
1173 template <typename T>
1174 using shape_t = typename T::shape_type;
1175 
1176 template <typename T>
1177 using pmap_t = typename T::pmap_interface;
1178 
1179 template <typename T>
1180 using policy_t = typename T::policy_type;
1181 
1185 template <typename Base, typename Derived>
1187  : std::conditional<
1188  std::is_base_of<Base, typename std::decay<Derived>::type>::value,
1189  std::true_type, std::false_type>::type {};
1190 
1192 
1195 template <typename T>
1196 struct is_pair : public std::false_type {};
1197 
1198 template <typename T1, typename T2>
1199 struct is_pair<std::pair<T1, T2>> : public std::true_type {};
1200 
1202 template <typename T>
1203 constexpr const bool is_pair_v = is_pair<T>::value;
1204 
1206 
1216 template <typename T>
1217 struct is_initializer_list : std::false_type {};
1218 
1227 template <typename T>
1228 struct is_initializer_list<std::initializer_list<T>> : std::true_type {};
1229 
1239 template <typename T>
1240 static constexpr bool is_initializer_list_v = is_initializer_list<T>::value;
1241 
1243 
1246 template <typename T>
1247 static constexpr bool is_gpair_v =
1248  is_contiguous_range_v<T> || is_gettable_pair_v<T>;
1249 
1253 template <typename T, typename Enabler = void>
1254 struct is_gpair_range : std::false_type {};
1255 
1256 template <typename T>
1258  std::enable_if_t<is_gpair_v<value_t<T>> && is_range_v<T>>>
1259  : std::true_type {};
1260 
1262 template <typename T>
1263 static constexpr bool is_gpair_range_v = is_gpair_range<T>::value;
1264 
1266 template <typename GeneralizedPair,
1267  typename = std::enable_if_t<is_gpair_v<GeneralizedPair>>>
1268 decltype(auto) at(GeneralizedPair&& v, std::size_t idx) {
1269  assert(idx == 0 || idx == 1);
1270  if constexpr (is_gettable_pair_v<std::decay_t<decltype(v)>>) {
1271 #if __cplusplus <= 201703L
1272  return idx == 0 ? detail::get<0>(v) : detail::get<1>(v);
1273 #else
1274  return idx == 0 ? get<0>(v) : get<1>(v);
1275 #endif
1276  } else if constexpr (is_contiguous_range_v<std::decay_t<decltype(v)>>) {
1277  assert(std::size(v) == 2);
1278  return std::data(v)[idx];
1279  }
1280  abort(); // unreachable
1281 };
1282 
1284 // https://stackoverflow.com/questions/51187974/can-stdis-invocable-be-emulated-within-c11
1285 
1286 template <typename F, typename... Args>
1288  : std::is_constructible<
1289  std::function<void(Args...)>,
1290  std::reference_wrapper<typename std::remove_reference<F>::type>> {};
1291 
1292 template <typename R, typename F, typename... Args>
1294  : std::is_constructible<
1295  std::function<R(Args...)>,
1296  std::reference_wrapper<typename std::remove_reference<F>::type>> {};
1297 
1298 template <typename Enabler, typename F, typename... Args>
1299 struct is_invocable_void_helper : std::false_type {};
1300 template <typename F, typename... Args>
1302  std::enable_if_t<std::is_void<std::result_of_t<F(Args...)>>::value, void>,
1303  F, Args...> : std::true_type {};
1304 template <typename F, typename... Args>
1305 struct is_invocable_void : is_invocable_void_helper<void, F, Args...> {};
1306 
1307 template <typename T>
1309 } // namespace detail
1310 
1311 } // namespace TiledArray
1312 
1313 #endif // TILEDARRAY_TYPE_TRAITS_H__INCLUDED
Detect a lazy evaluation tile that are not a LazyArrayTile.
Definition: type_traits.h:690
decltype(auto) subt(const Tile< Left > &left, const Tile< Right > &right)
Subtract tile arguments.
Definition: tile.h:879
constexpr const bool is_array_tile_v
is_array_tile_v<T> is an alias for is_array_tile<T>::value
Definition: type_traits.h:678
std::add_lvalue_reference< typename std::add_const< T >::type >::type type
Definition: type_traits.h:972
constexpr const bool is_pair_v
is_pair_v<T> is an alias for is_pair<T>::value
Definition: type_traits.h:1203
constexpr const bool is_integral_pair_v
is_integral_pair_v<T> is an alias for is_integral_pair<T>::value
Definition: type_traits.h:909
typename make_void< Ts... >::type void_t
Definition: type_traits.h:55
Primary template for detecting if T is an std::initializer_list.
Definition: type_traits.h:1217
remove_cvr_t< decltype(*std::begin(std::declval< T & >()))> value_t
Definition: type_traits.h:1113
constexpr const bool is_type_v
Definition: type_traits.h:393
Consumable tile type trait.
Definition: type_traits.h:611
constexpr const bool is_non_array_lazy_tile_v
Definition: type_traits.h:696
static auto test(void *) -> decltype(std::add_pointer_t< decltype(std::declval< U >()< std::declval< U >())>
Definition: type_traits.h:767
typename TiledArray::detail::numeric_type< T >::type numeric_t
numeric_t<T> is an alias for numeric_type<T>::type
Definition: type_traits.h:730
typename T::shape_type shape_t
Definition: type_traits.h:1174
decltype(std::declval< Scalar1 >() *std::declval< Scalar2 >()) mult_t
Definition: type_traits.h:1159
constexpr const bool is_integral_tuple_v
is_integral_tuple_v<T> is an alias for is_integral_tuple<T>::value
Definition: type_traits.h:952
#define GENERATE_HAS_MEMBER_TYPE(Type)
Definition: type_traits.h:127
void permute(InputOp &&input_op, OutputOp &&output_op, Result &result, const Perm &perm, const Arg0 &arg0, const Args &... args)
Construct a permuted tensor copy.
Definition: permute.h:117
constexpr const bool is_std_gettable_v
Definition: type_traits.h:840
helper to implement other metafunctions is_type<T>::value is true if T is a valid type
Definition: type_traits.h:389
auto get(T &&t)
Definition: type_traits.h:858
typename T::pmap_interface pmap_t
Definition: type_traits.h:1177
std::random_access_iterator_tag iterator_category
Definition: type_traits.h:1019
Type trait for extracting the scalar type of tensors and arrays.
Definition: type_traits.h:744
constexpr const bool is_gettable_v
Definition: type_traits.h:854
constexpr const bool is_scalar_v
is_scalar_v<T> is an alias for is_scalar_v<T>
Definition: type_traits.h:659
constexpr bool is_integral_v
Definition: type_traits.h:61
Tile< Result > & mult_to(Tile< Result > &result, const Tile< Arg > &arg)
Multiply to the result tile.
Definition: tile.h:1081
constexpr const bool is_gettable_pair_v
is_gettable_pair_v<T> is an alias for is_gettable_pair<T>::value
Definition: type_traits.h:888
std::random_access_iterator_tag iterator_category
Definition: type_traits.h:1014
Lazy tile for on-the-fly evaluation of array tiles.
Definition: array_eval.h:42
constexpr const bool has_conversion_operator_v
Definition: type_traits.h:496
typename T::policy_type policy_t
Definition: type_traits.h:1180
constexpr const bool is_complete_type_v
Definition: type_traits.h:412
std::enable_if_t< is_numeric_v< T >, U > enable_if_numeric_t
SFINAE type for enabling code when T is a numeric type.
Definition: type_traits.h:649
decltype(auto) add(const Tile< Left > &left, const Tile< Right > &right)
Add tile arguments.
Definition: tile.h:734
constexpr const bool is_integral_pair_list_v
Definition: type_traits.h:939
decltype(std::begin(std::declval< T & >())) iterator_t
Definition: type_traits.h:1106
constexpr const bool is_boost_gettable_v
Definition: type_traits.h:851
typename TiledArray::detail::scalar_type< T >::type scalar_t
scalar_t<T> is an alias for scalar_type<T>::type
Definition: type_traits.h:760
decltype(std::declval< Scalar1 >() - std::declval< Scalar2 >()) subt_t
Definition: type_traits.h:1156
constexpr const bool is_explicitly_convertible_v
Definition: type_traits.h:508
Tile< Result > & add_to(Tile< Result > &result, const Tile< Arg > &arg)
Add to the result tile.
Definition: tile.h:831
Remove const, volatile, and reference qualifiers.
Definition: type_traits.h:956
decltype(auto) mult(const Tile< Left > &left, const Tile< Right > &right)
Multiplication tile arguments.
Definition: tile.h:1018
constexpr const bool is_consumable_tile_v
is_consumable_tile_v<T> is an alias for is_consumable_tile<T>::value
Definition: type_traits.h:618
typename param< U >::type param_type
Definition: type_traits.h:991
Forward declarations.
Definition: dist_array.h:57
typename std::conditional< B, const T, T >::type const_if_t
prepends const to T if B is true
Definition: type_traits.h:966
constexpr const bool is_integral_list_v
is_integral_list_v<T> is an alias for is_integral_list<T>::value
Definition: type_traits.h:812
constexpr const bool is_complex_v
is_complex_v<T> is an alias for is_complex<T>::value
Definition: type_traits.h:632
typename T::trange_type trange_t
Definition: type_traits.h:1171
constexpr const bool is_lazy_tile_v
is_lazy_tile_v<T> is an alias for is_lazy_tile<T>::value
Definition: type_traits.h:598
Place-holder object for a zero tensor.
Definition: zero_tensor.h:32
constexpr bool empty()
Test for empty tensors in an empty list.
Definition: utility.h:320
constexpr const bool is_numeric_v
is_numeric_v<T> is an alias for is_numeric<T>::value
Definition: type_traits.h:645
decltype(std::declval< Scalar1 >()+std::declval< Scalar2 >()) add_t
Definition: type_traits.h:1153
#define GENERATE_IS_FREE_FUNCTION_ANYRETURN(Function)
Definition: type_traits.h:244
typename remove_cvr< T >::type remove_cvr_t
Definition: type_traits.h:962
helper to implement other metafunctions is_complete_type<T>::value is true if T is a complete type
Definition: type_traits.h:401
constexpr const bool is_strictly_ordered_v
is_strictly_ordered_v<T> is an alias for is_strictly_ordered<T>::value
Definition: type_traits.h:786
Detect tiles used by ArrayEvalImpl.
Definition: type_traits.h:670
std::remove_cv< typename std::remove_reference< T >::type >::type type
Definition: type_traits.h:958
Type trait for extracting the numeric type of tensors and arrays.
Definition: type_traits.h:709
Tile< Result > & subt_to(Tile< Result > &result, const Tile< Arg > &arg)
Subtract from the result tile.
Definition: tile.h:972
Determine the object type used in the evaluation of tensor expressions.
Definition: type_traits.h:580
non_iterator_tag iterator_category
Definition: type_traits.h:997
decltype(auto) at(GeneralizedPair &&v, std::size_t idx)
at(pair, i) extracts i-th element from gpair
Definition: type_traits.h:1268
constexpr const bool is_tuple_v
is_tuple_v<T> is an alias for is_tuple<T>::value
Definition: type_traits.h:826
#define GENERATE_HAS_MEMBER_FUNCTION(Member)
Definition: type_traits.h:169
constexpr const bool is_implicitly_convertible_v
Definition: type_traits.h:521
constexpr const bool is_convertible_v
Definition: type_traits.h:537
Detect lazy evaluation tiles.
Definition: type_traits.h:591
std::random_access_iterator_tag iterator_category
Definition: type_traits.h:1009
An N-dimensional shallow copy wrapper for tile objects.
Definition: tile.h:82
#define GENERATE_HAS_MEMBER_FUNCTION_ANYRETURN(Member)
Definition: type_traits.h:211