From cdaaefd82f48e64ec8aca0ed39642ef9d0135632 Mon Sep 17 00:00:00 2001
From: Yichao Yu <yyc1992@gmail.com>
Date: Thu, 19 Jun 2014 08:24:15 +0800
Subject: [PATCH] c++14 style helper templates, convert pyopencl_buf to
 ArgBuffer

---
 src/c_wrapper/clobj.h    | 12 ++----
 src/c_wrapper/error.h    |  8 ++--
 src/c_wrapper/function.h | 19 ++++-----
 src/c_wrapper/utils.h    | 86 ++++++++++++++++++++++------------------
 4 files changed, 64 insertions(+), 61 deletions(-)

diff --git a/src/c_wrapper/clobj.h b/src/c_wrapper/clobj.h
index fed644e5..660dd3ba 100644
--- a/src/c_wrapper/clobj.h
+++ b/src/c_wrapper/clobj.h
@@ -53,10 +53,8 @@ print_clobj(std::ostream &stm, const CLObj *obj)
 }
 
 template<typename CLObj>
-class CLArg<CLObj,
-            typename std::enable_if<
-                std::is_base_of<clobj<typename CLObj::cl_type>,
-                                CLObj>::value>::type> {
+class CLArg<CLObj, enable_if_t<std::is_base_of<clobj<typename CLObj::cl_type>,
+                                               CLObj>::value> > {
 private:
     CLObj &m_obj;
 public:
@@ -76,10 +74,8 @@ public:
 };
 
 template<typename CLObj>
-class CLArg<CLObj*,
-            typename std::enable_if<
-                std::is_base_of<clobj<typename CLObj::cl_type>,
-                                CLObj>::value>::type> {
+class CLArg<CLObj*, enable_if_t<std::is_base_of<clobj<typename CLObj::cl_type>,
+                                                CLObj>::value> > {
 private:
     CLObj *m_obj;
 public:
diff --git a/src/c_wrapper/error.h b/src/c_wrapper/error.h
index 1bf4ab9f..f77592a4 100644
--- a/src/c_wrapper/error.h
+++ b/src/c_wrapper/error.h
@@ -106,8 +106,7 @@ struct __CLPrintOut {
 };
 
 template<typename T>
-struct __CLPrintOut<T, typename std::enable_if<
-                           std::remove_reference<T>::type::is_out>::type> {
+struct __CLPrintOut<T, enable_if_t<rm_ref_t<T>::is_out> > {
     static inline void
     call(T v, std::ostream &stm)
     {
@@ -195,11 +194,10 @@ public:
 };
 
 template<typename... Types>
-static PYOPENCL_INLINE CLArgPack<typename std::remove_reference<Types>::type...>
+static PYOPENCL_INLINE CLArgPack<rm_ref_t<Types>...>
 make_clargpack(Types&&... args)
 {
-    return CLArgPack<typename std::remove_reference<Types>::type...>(
-        std::forward<Types>(args)...);
+    return CLArgPack<rm_ref_t<Types>...>(std::forward<Types>(args)...);
 }
 
 template<typename... ArgTypes2, typename... ArgTypes>
diff --git a/src/c_wrapper/function.h b/src/c_wrapper/function.h
index 495483c8..4277f730 100644
--- a/src/c_wrapper/function.h
+++ b/src/c_wrapper/function.h
@@ -12,6 +12,11 @@
 
 namespace pyopencl {
 
+template<typename T>
+using rm_ref_t = typename std::remove_reference<T>::type;
+template<bool B, class T = void>
+using enable_if_t = typename std::enable_if<B, T>::type;
+
 template<int...>
 struct seq {
 };
@@ -44,11 +49,8 @@ call_tuple(Function &&func, T &&args)
                       typename gens<std::tuple_size<T>::value>::type(), args);
 }
 
-template<typename T>
-using _ArgType = typename std::remove_reference<T>::type;
-
 template<template<typename...> class Convert, typename... Types>
-using _ArgPackBase = std::tuple<Convert<_ArgType<Types> >...>;
+using _ArgPackBase = std::tuple<Convert<rm_ref_t<Types> >...>;
 
 template<template<typename...> class Convert, typename... Types>
 class ArgPack : public _ArgPackBase<Convert, Types...> {
@@ -69,7 +71,7 @@ private:
     }
 
     template<typename T>
-    using ArgConvert = Convert<_ArgType<T> >;
+    using ArgConvert = Convert<rm_ref_t<T> >;
     template<template<typename...> class Getter, int... S>
     PYOPENCL_INLINE auto
     __get(seq<S...>)
@@ -84,7 +86,7 @@ private:
 public:
     template<typename... Types2>
     ArgPack(Types2&&... arg_orig)
-        : tuple_base(ArgConvert<_ArgType<Types> >(arg_orig)...)
+        : tuple_base(ArgConvert<rm_ref_t<Types> >(arg_orig)...)
     {
     }
     ArgPack(ArgPack<Convert, Types...> &&other)
@@ -109,11 +111,10 @@ public:
 };
 
 template<template<typename...> class Convert, typename... Types>
-static PYOPENCL_INLINE ArgPack<Convert, _ArgType<Types>...>
+static PYOPENCL_INLINE ArgPack<Convert, rm_ref_t<Types>...>
 make_argpack(Types&&... args)
 {
-    return ArgPack<Convert, _ArgType<Types>...>(
-        std::forward<Types>(args)...);
+    return ArgPack<Convert, rm_ref_t<Types>...>(std::forward<Types>(args)...);
 }
 
 }
diff --git a/src/c_wrapper/utils.h b/src/c_wrapper/utils.h
index bd39f4df..85810edd 100644
--- a/src/c_wrapper/utils.h
+++ b/src/c_wrapper/utils.h
@@ -197,11 +197,21 @@ public:
     }
 };
 
+template<ArgType AT, typename T, class = void>
+struct _ToArgBuffer {
+    static PYOPENCL_INLINE ArgBuffer<rm_ref_t<T>, AT>
+    convert(T &buf)
+    {
+        return ArgBuffer<rm_ref_t<T>, AT>(&buf, 1);
+    }
+};
+
 template<ArgType AT=ArgType::None, typename T>
-static PYOPENCL_INLINE ArgBuffer<T, AT>
-arg_buf(T &buf)
+static PYOPENCL_INLINE auto
+arg_buf(T &&buf)
+    -> decltype(_ToArgBuffer<AT, T>::convert(std::forward<T>(buf)))
 {
-    return ArgBuffer<T, AT>(&buf, 1);
+    return _ToArgBuffer<AT, T>::convert(std::forward<T>(buf));
 }
 
 template<ArgType AT=ArgType::None, typename T>
@@ -222,8 +232,8 @@ template<typename Buff, class = void>
 struct _ArgBufferConverter;
 
 template<typename Buff>
-struct _ArgBufferConverter<Buff, typename std::enable_if<
-                                     Buff::arg_type == ArgType::None>::type> {
+struct _ArgBufferConverter<Buff,
+                           enable_if_t<Buff::arg_type == ArgType::None> > {
     static PYOPENCL_INLINE typename Buff::type*
     convert(Buff &buff)
     {
@@ -232,8 +242,8 @@ struct _ArgBufferConverter<Buff, typename std::enable_if<
 };
 
 template<typename Buff>
-struct _ArgBufferConverter<Buff, typename std::enable_if<
-                                     Buff::arg_type == ArgType::SizeOf>::type> {
+struct _ArgBufferConverter<Buff,
+                           enable_if_t<Buff::arg_type == ArgType::SizeOf> > {
     static PYOPENCL_INLINE auto
     convert(Buff &buff)
         -> decltype(std::make_tuple(sizeof(typename Buff::type) * buff.len(),
@@ -245,8 +255,8 @@ struct _ArgBufferConverter<Buff, typename std::enable_if<
 };
 
 template<typename Buff>
-struct _ArgBufferConverter<Buff, typename std::enable_if<
-                                     Buff::arg_type == ArgType::Length>::type> {
+struct _ArgBufferConverter<Buff,
+                           enable_if_t<Buff::arg_type == ArgType::Length> > {
     static PYOPENCL_INLINE auto
     convert(Buff &buff)
         -> decltype(std::make_tuple(buff.len(), buff.get()))
@@ -256,15 +266,13 @@ struct _ArgBufferConverter<Buff, typename std::enable_if<
 };
 
 template<typename Buff>
-class CLArg<Buff, typename std::enable_if<std::is_base_of<
-                                              ArgBuffer<typename Buff::type,
+class CLArg<Buff, enable_if_t<std::is_base_of<ArgBuffer<typename Buff::type,
                                                         Buff::arg_type>,
-                                              Buff>::value>::type> {
+                                              Buff>::value> > {
 private:
     Buff &m_buff;
 public:
-    constexpr static bool is_out = !(std::is_const<Buff>::value ||
-                                     std::is_const<typename Buff::type>::value);
+    constexpr static bool is_out = !std::is_const<typename Buff::type>::value;
     CLArg(Buff &buff) noexcept
         : m_buff(buff)
     {}
@@ -306,8 +314,7 @@ struct OutArg {
 };
 
 template<typename T>
-class CLArg<T, typename std::enable_if<
-                      std::is_base_of<OutArg, T>::value>::type> {
+class CLArg<T, enable_if_t<std::is_base_of<OutArg, T>::value> > {
 private:
     bool m_converted;
     bool m_need_cleanup;
@@ -412,35 +419,36 @@ public:
     }
 };
 
+template<typename T, class = void>
+struct is_pyopencl_buf {
+    constexpr static bool value = false;
+};
+
+template<typename T>
+struct is_pyopencl_buf<
+    T, enable_if_t<std::is_base_of<pyopencl_buf<typename T::element_type>,
+                                   T>::value> > {
+    constexpr static bool value = true;
+};
+
 template<typename Buff>
-class CLArg<Buff, typename std::enable_if<
-                      std::is_base_of<
-                          pyopencl_buf<typename Buff::element_type>,
-                          Buff>::value>::type> {
-private:
-    Buff &m_buff;
+using __pyopencl_buf_arg_type =
+    rm_ref_t<decltype(std::declval<Buff>().to_arg())>;
+
+template<typename Buff>
+class CLArg<Buff, enable_if_t<is_pyopencl_buf<Buff>::value> >
+    : public CLArg<__pyopencl_buf_arg_type<Buff> > {
+    typedef __pyopencl_buf_arg_type<Buff> BufType;
+    BufType m_buff;
 public:
-    constexpr static bool is_out =
-        !(std::is_const<Buff>::value ||
-          std::is_const<typename Buff::element_type>::value);
+    PYOPENCL_INLINE
     CLArg(Buff &buff) noexcept
-        : m_buff(buff)
+        : CLArg<BufType>(m_buff), m_buff(buff.to_arg())
     {}
+    PYOPENCL_INLINE
     CLArg(CLArg<Buff> &&other) noexcept
-        : m_buff(other.m_buff)
+        : CLArg<BufType>(m_buff), m_buff(std::move(other.m_buff))
     {}
-    PYOPENCL_INLINE auto
-    convert() const noexcept
-        -> decltype(std::make_tuple(m_buff.len(), m_buff.get()))
-    {
-        return std::make_tuple(m_buff.len(), m_buff.get());
-    }
-    PYOPENCL_INLINE void
-    print(std::ostream &stm, bool out=false)
-    {
-        print_buf(stm, m_buff.get(), m_buff.len(), ArgType::Length,
-                  out || !is_out, out);
-    }
 };
 
 template<typename T>
-- 
GitLab