Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work around compiler bug in msvc 14.25; fixes #1453 #1454

Merged
merged 3 commits into from
Mar 19, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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