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