CanBeCalled.h
Go to the documentation of this file.
1/*!
2 *
3 *
4 * \brief Template class checking whether for a functor F and Argument U, F(U) can be called.
5 *
6 * \par Implementation is based on
7 * http://www.boost.org/doc/libs/1_52_0/doc/html/proto/appendices.html
8 *
9 *
10 *
11 * \author O. Krause
12 * \date 2013
13 *
14 *
15 * \par Copyright 1995-2017 Shark Development Team
16 *
17 * <BR><HR>
18 * This file is part of Shark.
19 * <https://shark-ml.github.io/Shark/>
20 *
21 * Shark is free software: you can redistribute it and/or modify
22 * it under the terms of the GNU Lesser General Public License as published
23 * by the Free Software Foundation, either version 3 of the License, or
24 * (at your option) any later version.
25 *
26 * Shark is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU Lesser General Public License for more details.
30 *
31 * You should have received a copy of the GNU Lesser General Public License
32 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
33 *
34 */
35
36#include <type_traits>
37
38 namespace shark{
39
40 ///\brief detects whether Functor(Argument) can be called.
41 ///
42 ///Suppose you have a general Functor. It might take several arguments,
43 ///some more suited for your computation than others. In this case one may
44 ///want to check, which input argument may work.
45 ///The exact implementation and inner workings are outlined in
46 ///http://www.boost.org/doc/libs/1_52_0/doc/html/proto/appendices.html
47 ///the trick is to generate a functor F2 from our supplied functor, such that
48 /// F2(arg) is always a valid expression, but at the same time F2(arg) and F(arg)
49 /// have clearly distinguishable return types. There are a few tricks needed for the
50 /// case that F(arg) has return type void.
51 template<class Functor, class Argument>
53 private:
54 struct dont_care
55 {
56 dont_care(...);
57 };
58 struct private_type
59 {
60 private_type const &operator,(int) const;
61 };
62
63 typedef char yes_type; // sizeof(yes_type) == 1
64 typedef char (&no_type)[2]; // sizeof(no_type) == 2
65
66 template<typename T>
67 static no_type is_private_type(T const &);
68
69 static yes_type is_private_type(private_type const &);
70
71 template<typename Fun>
72 struct funwrap : Fun
73 {
74 funwrap();
75 typedef private_type const &(*pointer_to_function)(dont_care);
76 operator pointer_to_function() const;
77 };
78
79 static funwrap<Functor> & m_fun;
80 static Argument & m_arg;
81 public:
82 static bool const value = (
83 sizeof(no_type) == sizeof(is_private_type( (m_fun(m_arg), 0) ))
84 );
85
86 typedef std::integral_constant<bool, value> type;
87 };
88
89 template<class R, class T, class Argument>
90 struct CanBeCalled<R(T), Argument>{
91 typedef std::integral_constant<bool, std::is_convertible<T, Argument>::value > type;
92 static bool const value = type::value;
93 };
94 template<class R, class T, class Argument>
95 struct CanBeCalled<R(*)(T), Argument>{
96 typedef std::integral_constant<bool, std::is_convertible<T, Argument>::value > type;
97 static bool const value = type::value;
98 };
99}