Expression SFINAE fixes in ApplyTuple
authorElizabeth Smith <elizabeths@fb.com>
Thu, 8 May 2014 15:20:48 +0000 (08:20 -0700)
committerDave Watson <davejwatson@fb.com>
Tue, 20 May 2014 19:53:58 +0000 (12:53 -0700)
Summary:
MSVC does not support Expression SFINAE

http://stackoverflow.com/questions/12654067

this is a very nice c++11 feature that makes for some nice clean templating

But of course MSVC can't have nice things - it partially implements this when it feels like it, so some will work and some will need the nonsense

@override-unit-failures

There will be more of these little template helper fixes  - they make the code a bit more complex but don't actually change anything when compiled

The accompanying fix in the test also does nothing but work around an MSVC compiler bug where it loses it's mind over the global namespace

Test Plan: fbconfig -r folly && fbmake runtests

Reviewed By: delong.j@fb.com

FB internal diff: D1312700

folly/ApplyTuple.h
folly/test/ApplyTupleTest.cpp

index 3fe30c3d1b996c04c9de8f0d210e89e3828b25f7..6fe6093d5a4ccdd8c34fe32af77405ee7d161889 100644 (file)
@@ -51,13 +51,24 @@ struct DerefSize
   : std::tuple_size<typename std::remove_reference<Tuple>::type>
 {};
 
+template<class Tuple, class ...Unpacked> struct ExprDoUnpack {
+  enum {
+    value = sizeof...(Unpacked) < DerefSize<Tuple>::value
+  };
+};
+
+template<class Tuple, class ...Unpacked> struct ExprIsUnpacked {
+  enum {
+    value = sizeof...(Unpacked) == DerefSize<Tuple>::value
+  };
+};
+
 // CallTuple recursively unpacks tuple arguments so we can forward
 // them into the function.
 template<class Ret>
 struct CallTuple {
   template<class F, class Tuple, class ...Unpacked>
-  static typename std::enable_if<
-    (sizeof...(Unpacked) < DerefSize<Tuple>::value),
+  static typename std::enable_if<ExprDoUnpack<Tuple, Unpacked...>::value,
     Ret
   >::type call(const F& f, Tuple&& t, Unpacked&&... unp) {
     typedef typename std::tuple_element<
@@ -71,8 +82,7 @@ struct CallTuple {
   }
 
   template<class F, class Tuple, class ...Unpacked>
-  static typename std::enable_if<
-    (sizeof...(Unpacked) == DerefSize<Tuple>::value),
+  static typename std::enable_if<ExprIsUnpacked<Tuple, Unpacked...>::value,
     Ret
   >::type call(const F& f, Tuple&& t, Unpacked&&... unp) {
     return makeCallable(f)(std::forward<Unpacked>(unp)...);
index 0f83194266a80bb72c709e95e43368de177f5b43..7ddac05f113c9cf3952f1bab3df3e6930116fb60 100644 (file)
 
 #include <memory>
 
+// this placates visual studio stupidity - see
+// http://stackoverflow.com/questions/5503901
+namespace {}
+
 namespace {
 
 void func(int a, int b, double c) {