1 /***************************************************************************
2 * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht          *
3 * Copyright (c) QuantStack                                                 *
4 *                                                                          *
5 * Distributed under the terms of the BSD 3-Clause License.                 *
6 *                                                                          *
7 * The full license is in the file LICENSE, distributed with this software. *
8 ****************************************************************************/
9 
10 #ifndef XTENSOR_VECTORIZE_HPP
11 #define XTENSOR_VECTORIZE_HPP
12 
13 #include <type_traits>
14 #include <utility>
15 
16 #include "xfunction.hpp"
17 #include "xutils.hpp"
18 
19 namespace xt
20 {
21 
22     /***************
23      * xvectorizer *
24      ***************/
25 
26     template <class F, class R>
27     class xvectorizer
28     {
29     public:
30 
31         template <class... E>
32         using xfunction_type = xfunction<F, xclosure_t<E>...>;
33 
34         template <class Func, class = std::enable_if_t<!std::is_same<std::decay_t<Func>, xvectorizer>::value>>
35         xvectorizer(Func&& f);
36 
37         template <class... E>
38         xfunction_type<E...> operator()(E&&... e) const;
39 
40     private:
41 
42         typename std::remove_reference<F>::type m_f;
43     };
44 
45     namespace detail
46     {
47         template <class F>
48         using get_function_type = remove_class_t<decltype(&std::remove_reference_t<F>::operator())>;
49     }
50 
51     template <class R, class... Args>
52     xvectorizer<R (*)(Args...), R> vectorize(R (*f)(Args...));
53 
54     template <class F, class R, class... Args>
55     xvectorizer<F, R> vectorize(F&& f, R (*)(Args...));
56 
57 // Workaround for Visual Studio 15.7.1.
58 // Error C2668 (ambiguous call to overloaded function) mistaking a declarations
59 // for the definition of another overload.
60 #ifndef _MSC_VER
61     template <class F>
62     auto vectorize(F&& f) -> decltype(vectorize(std::forward<F>(f), std::declval<detail::get_function_type<F>*>()));
63 #endif
64 
65     /******************************
66      * xvectorizer implementation *
67      ******************************/
68 
69     template <class F, class R>
70     template <class Func, class>
xvectorizer(Func && f)71     inline xvectorizer<F, R>::xvectorizer(Func&& f)
72         : m_f(std::forward<Func>(f))
73     {
74     }
75 
76     template <class F, class R>
77     template <class... E>
operator ()(E &&...e) const78     inline auto xvectorizer<F, R>::operator()(E&&... e) const -> xfunction_type<E...>
79     {
80         return xfunction_type<E...>(m_f, std::forward<E>(e)...);
81     }
82 
83     template <class R, class... Args>
vectorize(R (* f)(Args...))84     inline xvectorizer<R (*)(Args...), R> vectorize(R (*f)(Args...))
85     {
86         return xvectorizer<R (*)(Args...), R>(f);
87     }
88 
89     template <class F, class R, class... Args>
vectorize(F && f,R (*)(Args...))90     inline xvectorizer<F, R> vectorize(F&& f, R (*)(Args...))
91     {
92         return xvectorizer<F, R>(std::forward<F>(f));
93     }
94 
95     template <class F>
vectorize(F && f)96     inline auto vectorize(F&& f) -> decltype(vectorize(std::forward<F>(f), std::declval<detail::get_function_type<F>*>()))
97     {
98         return vectorize(std::forward<F>(f), static_cast<detail::get_function_type<F>*>(nullptr));
99     }
100 }
101 
102 #endif
103