Workaround MSVC bug with referencing template constructors before definition
authorAndrew Krieger <andrew.krieger@oculus.com>
Wed, 18 Oct 2017 22:44:01 +0000 (15:44 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 18 Oct 2017 22:51:42 +0000 (15:51 -0700)
Summary:
MSVC has a bug where it is unable to match an out-of-line constructor (and
possibly other kind of member) to the definition if it is implicitly referenced
before the definition is processed. The guilty method is
SemiFuture<Unit> makeSemiFuture(). Moving it after the constructor definitions
resolves the issue.

Reviewed By: yfeldblum

Differential Revision: D6042277

fbshipit-source-id: 97fe97c0edf3df3d9e3b808968b450c73959b600

folly/futures/Future-inl.h

index cdd38f7..c6ea59a 100644 (file)
@@ -136,10 +136,6 @@ SemiFuture<typename std::decay<T>::type> makeSemiFuture(T&& t) {
   return makeSemiFuture(Try<typename std::decay<T>::type>(std::forward<T>(t)));
 }
 
-inline SemiFuture<Unit> makeSemiFuture() {
-  return makeSemiFuture(Unit{});
-}
-
 // makeSemiFutureWith(SemiFuture<T>()) -> SemiFuture<T>
 template <class F>
 typename std::enable_if<
@@ -246,6 +242,12 @@ SemiFuture<T>::~SemiFuture() {
   detach();
 }
 
+// This must be defined after the constructors to avoid a bug in MSVC
+// https://connect.microsoft.com/VisualStudio/feedback/details/3142777/out-of-line-constructor-definition-after-implicit-reference-causes-incorrect-c2244
+inline SemiFuture<Unit> makeSemiFuture() {
+  return makeSemiFuture(Unit{});
+}
+
 template <class T>
 T& SemiFuture<T>::value() & {
   throwIfInvalid();