Explorar el Código

Merge branch 'fluent-conversion'

* fluent-conversion:
  Make the template constructor work - looks like the answer is to not use type_traits.
  Make conversions no longer quite so awful by providing an internal-only cast function 'as<T>()'.
Sam Jaffe hace 5 años
padre
commit
b4771de2f0

+ 0 - 16
include/opaque_typedef/convertable.hpp

@@ -1,16 +0,0 @@
-#pragma once
-
-namespace types {
-  
-  template <typename To>
-  struct Convertable {
-    template <typename Self>
-    class type {
-    private:
-      Self const & self() const { return *(Self const *)(void const *)(this); }
-    public:
-      operator To() const;
-    };
-  };
-  
-}

+ 14 - 4
include/opaque_typedef/opaque_typedef.hpp

@@ -10,14 +10,22 @@
 #pragma once
 
 #include "comparable.hpp"
-#include "convertable.hpp"
 
 namespace types {
+  template <typename Base, typename Tag, template <typename> class... Skills>
+  class opaque_typedef;
+  
+  template <typename T> struct is_opaque_typedef {
+    constexpr static bool const value = false;
+  };
+  
+  template <typename B, typename T, template <typename> class... S>
+  struct is_opaque_typedef<opaque_typedef<B, T, S...>> {
+    constexpr static bool const value = true;
+  };
+
   template <typename Base, typename Tag, template <typename> class... Skills>
   class opaque_typedef : public Skills<opaque_typedef<Base, Tag, Skills...>>... {
-  public:
-    using super = opaque_typedef;
-    
   private:
     Base value_;
     
@@ -25,6 +33,8 @@ namespace types {
     opaque_typedef() = default;
     explicit opaque_typedef(Base const & value) : value_(value) {};
     explicit opaque_typedef(Base && value) : value_(std::forward<Base>(value)) {};
+    template <typename B, typename T, template <typename> class... S>
+    opaque_typedef(opaque_typedef<B, T, S...> const & other);
     
     Base const & get() const { return value_; }
     explicit operator Base const &() const { return value_; }

+ 6 - 17
test/opaque_typedef_test.cpp

@@ -10,25 +10,14 @@
 
 #include "opaque_typedef/opaque_typedef.hpp"
 
-struct degree;
-struct radian;
+using degree = types::opaque_typedef<double, struct degree_tag, types::Comparable>;
+using radian = types::opaque_typedef<double, struct radian_tag, types::Comparable>;
 
-struct degree : types::opaque_typedef<double, struct degree_tag, types::Comparable, types::Convertable<radian>::type> {
-  using super::super;
-};
-struct radian : types::opaque_typedef<double, struct radian_tag, types::Comparable, types::Convertable<degree>::type> {
-  using super::super;
-};
+template <> template <>radian::opaque_typedef(degree const & other)
+    : radian(other.get() * M_PI_2 / 90.0) {}
 
-template<> template <>
-types::Convertable<degree>::type<radian::super>::operator degree() const {
-  return degree{ self().get() * 90.0 / M_PI_2 };
-}
-
-template <> template <>
-types::Convertable<radian>::type<degree::super>::operator radian() const {
-  return radian{ self().get() * M_PI_2 / 90.0 };
-}
+template <> template <> degree::opaque_typedef(radian const & other)
+    : degree(other.get() * 90.0 / M_PI_2) {}
 
 void PrintTo(radian const & ot, std::ostream * os) {
   (*os) << double(ot)/M_PI << "π";