Skip to content

Commit

Permalink
Work around compiler bug in msvc 14.25; fixes #1453 (#1454)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericniebler authored Mar 19, 2020
1 parent 8f0e898 commit 794c2e7
Showing 1 changed file with 31 additions and 48 deletions.
79 changes: 31 additions & 48 deletions include/concepts/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@
/**/
#else // ^^^ workaround / no workaround vvv
#define CPP_broken_friend_member \
template<std::true_type (&CPP_true)(::concepts::detail::xNil) = \
template<::concepts::detail::boolean_true_t (&CPP_true)(::concepts::detail::xNil) = \
::concepts::detail::CPP_true> \
/**/
#endif // CPP_WORKAROUND_MSVC_779763
Expand Down Expand Up @@ -746,20 +746,14 @@ namespace concepts
return true;
}

struct boolean
{
friend bool operator&&(boolean, bool) = delete;
friend bool operator&&(bool, boolean) = delete;
friend bool operator||(boolean, bool) = delete;
friend bool operator||(bool, boolean) = delete;
};
template<typename T, typename U>
struct and_;
template<typename T, typename U>
struct or_;
template<typename T>
struct not_ : boolean
struct not_
{
using _cpp_boolean_t = not_;
constexpr operator bool() const noexcept
{
return !(bool) T{};
Expand All @@ -769,20 +763,21 @@ namespace concepts
return T{};
}
template<typename That>
constexpr and_<not_, That> operator&&(That) const noexcept
constexpr and_<not_, typename That::_cpp_boolean_t> operator&&(That) const noexcept
{
return {};
}
template<typename That>
constexpr or_<not_, That> operator||(That) const noexcept
constexpr or_<not_, typename That::_cpp_boolean_t> operator||(That) const noexcept
{
return {};
}
};

template<typename T, typename U>
struct and_ : boolean
struct and_
{
using _cpp_boolean_t = and_;
static constexpr bool impl(std::false_type) noexcept
{
return false;
Expand All @@ -800,28 +795,21 @@ namespace concepts
return not_<and_>{};
}
template<typename That>
constexpr and_<and_, That> operator&&(That) const noexcept
constexpr and_<and_, typename That::_cpp_boolean_t> operator&&(That) const noexcept
{
static_assert(
!META_IS_SAME(That, bool),
"All expressions in a conjunction should be "
"defer:: concepts");
return {};
}
template<typename That>
constexpr or_<and_, That> operator||(That) const noexcept
constexpr or_<and_, typename That::_cpp_boolean_t> operator||(That) const noexcept
{
static_assert(
!META_IS_SAME(That, bool),
"All expressions in a disjunction should be "
"defer:: concepts");
return {};
}
};

template<typename T, typename U>
struct or_ : boolean
struct or_
{
using _cpp_boolean_t = or_;
static constexpr bool impl(std::true_type) noexcept
{
return true;
Expand All @@ -839,28 +827,21 @@ namespace concepts
return {};
}
template<typename That>
constexpr and_<or_, That> operator&&(That) const noexcept
constexpr and_<or_, typename That::_cpp_boolean_t> operator&&(That) const noexcept
{
static_assert(
!META_IS_SAME(That, bool),
"All expressions in a disjunction should be "
"defer:: concepts");
return {};
}
template<typename That>
constexpr or_<or_, That> operator||(That) const noexcept
constexpr or_<or_, typename That::_cpp_boolean_t> operator||(That) const noexcept
{
static_assert(
!META_IS_SAME(That, bool),
"All expressions in a disjunction should be "
"defer:: concepts");
return {};
}
};

template<class Fn>
struct boolean_ : boolean
struct boolean_
{
using _cpp_boolean_t = boolean_;
boolean_() = default;
constexpr boolean_(decltype(nullptr)) noexcept {}
template<bool = true>
Expand All @@ -873,21 +854,13 @@ namespace concepts
return {};
}
template<typename That>
constexpr and_<boolean_, That> operator&&(That) const noexcept
constexpr and_<boolean_, typename That::_cpp_boolean_t> operator&&(That) const noexcept
{
static_assert(
!META_IS_SAME(That, bool),
"All expressions in a disjunction should be "
"defer:: concepts");
return {};
}
template<typename That>
constexpr or_<boolean_, That> operator||(That) const noexcept
constexpr or_<boolean_, typename That::_cpp_boolean_t> operator||(That) const noexcept
{
static_assert(
!META_IS_SAME(That, bool),
"All expressions in a disjunction should be "
"defer:: concepts");
return {};
}
};
Expand All @@ -897,32 +870,42 @@ namespace concepts
struct Nil
{};

struct _true_fn
{
std::true_type operator()(int) const noexcept
{
return {};
}
};

using boolean_true_t = boolean_<_true_fn>;

#ifdef CPP_WORKAROUND_MSVC_779763
enum class xNil {};

struct CPP_true_t
{
constexpr std::true_type operator()(Nil) const noexcept
constexpr boolean_true_t operator()(Nil) const noexcept
{
return {};
}
constexpr std::true_type operator()(xNil) const noexcept
constexpr boolean_true_t operator()(xNil) const noexcept
{
return {};
}
};

CPP_INLINE_VAR constexpr CPP_true_t CPP_true_{};

constexpr std::true_type CPP_true(xNil)
constexpr boolean_true_t CPP_true(xNil)
{
return {};
}
#else
using xNil = Nil;
#endif

constexpr std::true_type CPP_true(Nil)
constexpr boolean_true_t CPP_true(Nil)
{
return {};
}
Expand Down

0 comments on commit 794c2e7

Please sign in to comment.