xvectorize.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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. #ifndef XTENSOR_VECTORIZE_HPP
  10. #define XTENSOR_VECTORIZE_HPP
  11. #include <type_traits>
  12. #include <utility>
  13. #include "xfunction.hpp"
  14. #include "xutils.hpp"
  15. namespace xt
  16. {
  17. /***************
  18. * xvectorizer *
  19. ***************/
  20. template <class F, class R>
  21. class xvectorizer
  22. {
  23. public:
  24. template <class... E>
  25. using xfunction_type = xfunction<F, xclosure_t<E>...>;
  26. template <class Func, class = std::enable_if_t<!std::is_same<std::decay_t<Func>, xvectorizer>::value>>
  27. xvectorizer(Func&& f);
  28. template <class... E>
  29. xfunction_type<E...> operator()(E&&... e) const;
  30. private:
  31. typename std::remove_reference<F>::type m_f;
  32. };
  33. namespace detail
  34. {
  35. template <class F>
  36. using get_function_type = remove_class_t<decltype(&std::remove_reference_t<F>::operator())>;
  37. }
  38. template <class R, class... Args>
  39. xvectorizer<R (*)(Args...), R> vectorize(R (*f)(Args...));
  40. template <class F, class R, class... Args>
  41. xvectorizer<F, R> vectorize(F&& f, R (*)(Args...));
  42. // Workaround for Visual Studio 15.7.1.
  43. // Error C2668 (ambiguous call to overloaded function) mistaking a declarations
  44. // for the definition of another overload.
  45. #ifndef _MSC_VER
  46. template <class F>
  47. auto vectorize(F&& f)
  48. -> decltype(vectorize(std::forward<F>(f), std::declval<detail::get_function_type<F>*>()));
  49. #endif
  50. /******************************
  51. * xvectorizer implementation *
  52. ******************************/
  53. template <class F, class R>
  54. template <class Func, class>
  55. inline xvectorizer<F, R>::xvectorizer(Func&& f)
  56. : m_f(std::forward<Func>(f))
  57. {
  58. }
  59. template <class F, class R>
  60. template <class... E>
  61. inline auto xvectorizer<F, R>::operator()(E&&... e) const -> xfunction_type<E...>
  62. {
  63. return xfunction_type<E...>(m_f, std::forward<E>(e)...);
  64. }
  65. template <class R, class... Args>
  66. inline xvectorizer<R (*)(Args...), R> vectorize(R (*f)(Args...))
  67. {
  68. return xvectorizer<R (*)(Args...), R>(f);
  69. }
  70. template <class F, class R, class... Args>
  71. inline xvectorizer<F, R> vectorize(F&& f, R (*)(Args...))
  72. {
  73. return xvectorizer<F, R>(std::forward<F>(f));
  74. }
  75. template <class F>
  76. inline auto vectorize(F&& f)
  77. -> decltype(vectorize(std::forward<F>(f), std::declval<detail::get_function_type<F>*>()))
  78. {
  79. return vectorize(std::forward<F>(f), static_cast<detail::get_function_type<F>*>(nullptr));
  80. }
  81. }
  82. #endif