Kokkos Core Kernels Package Version of the Day
Loading...
Searching...
No Matches
Kokkos_DetectionIdiom.hpp
1//@HEADER
2// ************************************************************************
3//
4// Kokkos v. 4.0
5// Copyright (2022) National Technology & Engineering
6// Solutions of Sandia, LLC (NTESS).
7//
8// Under the terms of Contract DE-NA0003525 with NTESS,
9// the U.S. Government retains certain rights in this software.
10//
11// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12// See https://kokkos.org/LICENSE for license information.
13// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14//
15//@HEADER
16#ifndef KOKKOS_DETECTION_IDIOM_HPP
17#define KOKKOS_DETECTION_IDIOM_HPP
18#ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
19#define KOKKOS_IMPL_PUBLIC_INCLUDE
20#define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DETECTIONIDIOM
21#endif
22
23#include <Kokkos_Macros.hpp> // FIXME doesn't actually need it if it wasn't
24 // for the header self-containment test
25
26#include <type_traits>
27
28// NOTE This header implements the detection idiom from Version 2 of the C++
29// Extensions for Library Fundamentals, ISO/IEC TS 19568:2017
30
31// I deliberately omitted detected_or which does not fit well with the rest
32// of the specification. In my opinion, it should be removed from the TS.
33
34namespace Kokkos {
35
36namespace Impl {
37// base class for nonesuch to inherit from so it is not an aggregate
38struct nonesuch_base {};
39
40// primary template handles all types not supporting the archetypal Op
41template <class Default, class /*AlwaysVoid*/, template <class...> class Op,
42 class... /*Args*/>
43struct detector {
44 using value_t = std::false_type;
45 using type = Default;
46};
47
48// specialization recognizes and handles only types supporting Op
49template <class Default, template <class...> class Op, class... Args>
50struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> {
51 using value_t = std::true_type;
52 using type = Op<Args...>;
53};
54} // namespace Impl
55
56struct nonesuch : private Impl::nonesuch_base {
57 ~nonesuch() = delete;
58 nonesuch(nonesuch const&) = delete;
59 void operator=(nonesuch const&) = delete;
60};
61
62template <template <class...> class Op, class... Args>
63using is_detected =
64 typename Impl::detector<nonesuch, void, Op, Args...>::value_t;
65
66template <template <class...> class Op, class... Args>
67using detected_t = typename Impl::detector<nonesuch, void, Op, Args...>::type;
68
69template <class Default, template <class...> class Op, class... Args>
70using detected_or_t = typename Impl::detector<Default, void, Op, Args...>::type;
71
72template <class Expected, template <class...> class Op, class... Args>
73using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
74
75template <class To, template <class...> class Op, class... Args>
76using is_detected_convertible =
77 std::is_convertible<detected_t<Op, Args...>, To>;
78
79template <template <class...> class Op, class... Args>
80inline constexpr bool is_detected_v = is_detected<Op, Args...>::value;
81
82template <class Expected, template <class...> class Op, class... Args>
83inline constexpr bool is_detected_exact_v =
84 is_detected_exact<Expected, Op, Args...>::value;
85
86template <class Expected, template <class...> class Op, class... Args>
87inline constexpr bool is_detected_convertible_v =
88 is_detected_convertible<Expected, Op, Args...>::value;
89
90} // namespace Kokkos
91
92#ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DETECTIONIDIOM
93#undef KOKKOS_IMPL_PUBLIC_INCLUDE
94#undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_DETECTIONIDIOM
95#endif
96#endif