diff --git a/CHANGELOG.md b/CHANGELOG.md index 8098a51f16..5b27e1929d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -126,6 +126,8 @@ different versioning scheme, following the Haskell community's * Fixed a bug in `bond::nullable` where it was not propagating an allocator to `T` when `allocator_type` was not explicitly defined. * Fixed a bug in `bond::make_box` where `const T&` was not handled correctly. +* The use of `bond::check_method` has been replaced with less restricting expression + SFINAE checks on supported compilers. [Issue #896](https://github.com/Microsoft/bond/issues/896) ### C# ### diff --git a/cpp/inc/bond/core/config.h b/cpp/inc/bond/core/config.h index 27b8fdeac4..33698b8097 100644 --- a/cpp/inc/bond/core/config.h +++ b/cpp/inc/bond/core/config.h @@ -16,16 +16,17 @@ // BOND_SIMPLE_JSON_PROTOCOL disabled by default #endif -#if defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_NOEXCEPT) -#define BOND_NO_CXX11_NOEXCEPT -#endif - // std::once seems problematic on Linux (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60662) // For now we use std::call_once only on MSVC and boost::call_once on GCC/Clang. #if defined(BOOST_NO_CXX11_HDR_MUTEX) || !defined(_MSC_VER) #define BOND_NO_CX11_HDR_MUTEX #endif +// MSVC 14 (VS 2015) has only a dangerous partial implementation of expression SFINAE. +#if defined(BOOST_NO_SFINAE_EXPR) || (defined(_MSC_VER) && (_MSC_VER < 1910)) +#define BOND_NO_SFINAE_EXPR +#endif + #if defined(BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION) #define BOND_NO_CXX14_RETURN_TYPE_DEDUCTION #endif diff --git a/cpp/inc/bond/core/detail/mpl.h b/cpp/inc/bond/core/detail/mpl.h index bff4bf4e37..fb84f2beee 100644 --- a/cpp/inc/bond/core/detail/mpl.h +++ b/cpp/inc/bond/core/detail/mpl.h @@ -17,11 +17,18 @@ #include -namespace bond +namespace bond { namespace detail { namespace mpl { -namespace detail { namespace mpl +template struct +make_void { + using type = void; +}; + +template +using void_t = typename make_void::type; + template struct identity @@ -125,6 +132,4 @@ inline auto try_apply(F&& f) } -}} // namespace mpl { namespace detail - -} // namespace bond +} } } // namespace bond::detail::mpl diff --git a/cpp/inc/bond/core/detail/omit_default.h b/cpp/inc/bond/core/detail/omit_default.h index 5152112c0b..93707fd63c 100644 --- a/cpp/inc/bond/core/detail/omit_default.h +++ b/cpp/inc/bond/core/detail/omit_default.h @@ -129,9 +129,11 @@ implements_field_omitting : std::false_type {}; +#ifdef BOND_NO_SFINAE_EXPR template struct implements_field_omitting : implements_field_omitting {}; +#endif // WriteFieldOmitted is an optional protocol writer method which is called for @@ -139,7 +141,14 @@ implements_field_omitting // be implemented by untagged protocols that allow omitting optional fields. template struct implements_field_omitting >::type> +#ifdef BOND_NO_SFINAE_EXPR + typename boost::enable_if >::type> +#else + detail::mpl::void_t().WriteFieldOmitted( + std::declval(), + std::declval(), + std::declval()))>> +#endif : std::true_type {}; @@ -147,7 +156,13 @@ implements_field_omitting struct implements_field_omitting >::type> +#ifdef BOND_NO_SFINAE_EXPR + typename boost::enable_if >::type> +#else + typename boost::enable_if().ReadFieldOmitted())>>::type> +#endif : std::true_type {}; @@ -198,19 +213,28 @@ implements_struct_begin_with_base template struct implements_struct_begin >::type> +#ifdef BOND_NO_SFINAE_EXPR + typename boost::enable_if >::type> +#else + detail::mpl::void_t().ReadStructBegin())>> +#endif : std::true_type {}; template struct implements_struct_begin_with_base >::type> +#ifdef BOND_NO_SFINAE_EXPR + typename boost::enable_if >::type> +#else + detail::mpl::void_t().ReadStructBegin(std::declval()))>> +#endif : std::true_type {}; // StructBegin template -typename boost::enable_if >::type +typename boost::enable_if_c::value + && !implements_struct_begin_with_base::value>::type StructBegin(Input& input, bool /*base*/) { return input.ReadStructBegin(); @@ -234,7 +258,8 @@ StructBegin(Input& /*input*/, bool /*base*/) // StructEnd template -typename boost::enable_if >::type +typename boost::enable_if_c::value + && !implements_struct_begin_with_base::value>::type StructEnd(Input& input, bool /*base*/) { return input.ReadStructEnd(); diff --git a/cpp/inc/bond/core/reflection.h b/cpp/inc/bond/core/reflection.h index 317c2c5b64..ceb992e036 100644 --- a/cpp/inc/bond/core/reflection.h +++ b/cpp/inc/bond/core/reflection.h @@ -350,9 +350,15 @@ template struct is_writer : std::false_type {}; - template struct -is_writer >::type> +is_writer >::type> +#else + detail::mpl::void_t().WriteStructBegin( + std::declval(), + std::declval()))>> +#endif : std::true_type {}; diff --git a/cpp/inc/bond/core/traits.h b/cpp/inc/bond/core/traits.h index 990bddf921..8f67ded117 100644 --- a/cpp/inc/bond/core/traits.h +++ b/cpp/inc/bond/core/traits.h @@ -114,6 +114,7 @@ get_protocol_writer, Output> }; +// Used only for older compilers for which BOND_NO_SFINAE_EXPR is defined. template struct check_method : std::true_type {}; diff --git a/cpp/inc/bond/protocol/encoding.h b/cpp/inc/bond/protocol/encoding.h index 7cd9e03dd0..75f0c20ce0 100644 --- a/cpp/inc/bond/protocol/encoding.h +++ b/cpp/inc/bond/protocol/encoding.h @@ -21,7 +21,12 @@ implements_varint_write template struct -implements_varint_write >::type> +implements_varint_write >::type> +#else + detail::mpl::void_t().WriteVariableUnsigned(std::declval()))>> +#endif : std::true_type {}; @@ -73,7 +78,12 @@ implements_varint_read template struct -implements_varint_read >::type> +implements_varint_read >::type> +#else + detail::mpl::void_t().ReadVariableUnsigned(std::declval()))>> +#endif : std::true_type {};