Home | History | Annotate | Line # | Download | only in Support
      1 //===--- MSVCErrorWorkarounds.h - Enable future<Error> in MSVC --*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // MSVC's promise/future implementation requires types to be default
     10 // constructible, so this header provides analogues of Error an Expected
     11 // that are default constructed in a safely destructible state.
     12 //
     13 // FIXME: Kill off this header and migrate all users to Error/Expected once we
     14 //        move to MSVC versions that support non-default-constructible types.
     15 //
     16 //===----------------------------------------------------------------------===//
     17 
     18 #ifndef LLVM_SUPPORT_MSVCERRORWORKAROUNDS_H
     19 #define LLVM_SUPPORT_MSVCERRORWORKAROUNDS_H
     20 
     21 #include "llvm/Support/Error.h"
     22 
     23 namespace llvm {
     24 
     25 // A default-constructible llvm::Error that is suitable for use with MSVC's
     26 // std::future implementation which requires default constructible types.
     27 class MSVCPError : public Error {
     28 public:
     29   MSVCPError() { (void)!!*this; }
     30 
     31   MSVCPError(MSVCPError &&Other) : Error(std::move(Other)) {}
     32 
     33   MSVCPError &operator=(MSVCPError Other) {
     34     Error::operator=(std::move(Other));
     35     return *this;
     36   }
     37 
     38   MSVCPError(Error Err) : Error(std::move(Err)) {}
     39 };
     40 
     41 // A default-constructible llvm::Expected that is suitable for use with MSVC's
     42 // std::future implementation, which requires default constructible types.
     43 template <typename T> class MSVCPExpected : public Expected<T> {
     44 public:
     45   MSVCPExpected()
     46       : Expected<T>(make_error<StringError>("", inconvertibleErrorCode())) {
     47     consumeError(this->takeError());
     48   }
     49 
     50   MSVCPExpected(MSVCPExpected &&Other) : Expected<T>(std::move(Other)) {}
     51 
     52   MSVCPExpected &operator=(MSVCPExpected &&Other) {
     53     Expected<T>::operator=(std::move(Other));
     54     return *this;
     55   }
     56 
     57   MSVCPExpected(Error Err) : Expected<T>(std::move(Err)) {}
     58 
     59   template <typename OtherT>
     60   MSVCPExpected(
     61       OtherT &&Val,
     62       std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
     63       : Expected<T>(std::move(Val)) {}
     64 
     65   template <class OtherT>
     66   MSVCPExpected(
     67       Expected<OtherT> &&Other,
     68       std::enable_if_t<std::is_convertible<OtherT, T>::value> * = nullptr)
     69       : Expected<T>(std::move(Other)) {}
     70 
     71   template <class OtherT>
     72   explicit MSVCPExpected(
     73       Expected<OtherT> &&Other,
     74       std::enable_if_t<!std::is_convertible<OtherT, T>::value> * = nullptr)
     75       : Expected<T>(std::move(Other)) {}
     76 };
     77 
     78 } // end namespace llvm
     79 
     80 #endif // LLVM_SUPPORT_MSVCERRORWORKAROUNDS_H
     81