PLaSK library

Loading...
Searching...
No Matches
metaprog.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
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, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__UTILS_METAPROG_H
15#define PLASK__UTILS_METAPROG_H
16
21#include <tuple>
22#include <type_traits>
23
24 namespace plask {
25
36 template <int nr, typename... types>
37 struct chooseType {
38 typedef typename std::tuple_element<nr, std::tuple<types...>>::type type;
39};
40
41//TODO better impl. but not compilable with GCC 4.6 (unimplemented)
42/*template <int nr, typename firstType, typename... restTypes> struct chooseType {
44 typedef typename chooseType<nr-1, restTypes...>::type type;
45};
46
47template <typename firstType, typename... restTypes> struct chooseType<0, firstType, restTypes...> {
48 typedef firstType type;
49};*/
50
51
52//http://talesofcpp.fusionfenix.com/post-11/true-story-call-me-maybe
53 namespace hyman {
54 template <typename T>
55 using always_void = void;
56
57 template <typename Expr, std::size_t Step = 0, typename Enable = void>
58 struct is_callable_impl
59 : is_callable_impl<Expr, Step + 1>
60 {};
61
62 // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
63 // and t1 is an object of type T or a reference to an object of type T or a
64 // reference to an object of a type derived from T;
65 template <typename F, typename T, typename ...Args>
66 struct is_callable_impl<F(T, Args...), 0,
67 always_void<decltype(
68 (std::declval<T>().*std::declval<F>())(std::declval<Args>()...)
69 )>
70 > : std::true_type
71 {};
72
73 // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T
74 // and t1 is not one of the types described in the previous item;
75 template <typename F, typename T, typename ...Args>
76 struct is_callable_impl<F(T, Args...), 1,
77 always_void<decltype(
78 ((*std::declval<T>()).*std::declval<F>())(std::declval<Args>()...)
79 )>
80 > : std::true_type
81 {};
82
83 // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an
84 // object of type T or a reference to an object of type T or a reference to an
85 // object of a type derived from T;
86 template <typename F, typename T>
87 struct is_callable_impl<F(T), 2,
88 always_void<decltype(
89 std::declval<T>().*std::declval<F>()
90 )>
91 > : std::true_type
92 {};
93
94 // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is
95 // not one of the types described in the previous item;
96 template <typename F, typename T>
97 struct is_callable_impl<F(T), 3,
98 always_void<decltype(
99 (*std::declval<T>()).*std::declval<F>()
100 )>
101 > : std::true_type
102 {};
103
104 // f(t1, t2, ..., tN) in all other cases.
105 template <typename F, typename ...Args>
106 struct is_callable_impl<F(Args...), 4,
107 always_void<decltype(
108 std::declval<F>()(std::declval<Args>()...)
109 )>
110 > : std::true_type
111 {};
112
113 template <typename Expr>
114 struct is_callable_impl<Expr, 5>
115 : std::false_type
116 {};
117}
118
122 template <typename Expr>
123 struct is_callable
124 : hyman::is_callable_impl<Expr>
125{};
126
127
128} // namespace plask
129
130
131#endif // PLASK__UTILS_METAPROG_H