Skip to content

Commit

Permalink
[c++] Replace bond::check_method with decltype
Browse files Browse the repository at this point in the history
The use of `bond::check_method` has been replaced with less restricting expression
SFINAE checks on supported compilers. 

Fixes #896
  • Loading branch information
ara-ayvazyan authored and chwarr committed May 16, 2018
1 parent 2685b75 commit b3ffdd5
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ different versioning scheme, following the Haskell community's
* Fixed a bug in `bond::nullable<T, Alloc>` 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# ###

Expand Down
9 changes: 5 additions & 4 deletions cpp/inc/bond/core/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 10 additions & 5 deletions cpp/inc/bond/core/detail/mpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,18 @@
#include <utility>


namespace bond
namespace bond { namespace detail { namespace mpl
{

namespace detail { namespace mpl
template <typename...> struct
make_void
{
using type = void;
};

template <typename... T>
using void_t = typename make_void<T...>::type;


template <typename T> struct
identity
Expand Down Expand Up @@ -125,6 +132,4 @@ inline auto try_apply(F&& f)
}


}} // namespace mpl { namespace detail

} // namespace bond
} } } // namespace bond::detail::mpl
37 changes: 31 additions & 6 deletions cpp/inc/bond/core/detail/omit_default.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,25 +129,40 @@ implements_field_omitting
: std::false_type {};


#ifdef BOND_NO_SFINAE_EXPR
template <typename T> struct
implements_field_omitting<T&>
: implements_field_omitting<T> {};
#endif


// WriteFieldOmitted is an optional protocol writer method which is called for
// omitted optional fields. It CAN be implemented by tagged protocols and MUST
// be implemented by untagged protocols that allow omitting optional fields.
template <typename Writer> struct
implements_field_omitting<Writer,
typename boost::enable_if<bond::check_method<void (Writer::*)(BondDataType, uint16_t, const Metadata&), &Writer::WriteFieldOmitted> >::type>
#ifdef BOND_NO_SFINAE_EXPR
typename boost::enable_if<check_method<void (Writer::*)(BondDataType, uint16_t, const Metadata&), &Writer::WriteFieldOmitted> >::type>
#else
detail::mpl::void_t<decltype(std::declval<Writer>().WriteFieldOmitted(
std::declval<BondDataType>(),
std::declval<uint16_t>(),
std::declval<Metadata>()))>>
#endif
: std::true_type {};


// ReadFieldOmitted is an optional protocol reader method which MUST be implemented
// by untagged protocols that allow omitting optional fields.
template <typename Input> struct
implements_field_omitting<Input,
typename boost::enable_if<bond::check_method<bool (Input::*)(), &Input::ReadFieldOmitted> >::type>
#ifdef BOND_NO_SFINAE_EXPR
typename boost::enable_if<check_method<bool (Input::*)(), &Input::ReadFieldOmitted> >::type>
#else
typename boost::enable_if<std::is_same<
bool,
decltype(std::declval<Input>().ReadFieldOmitted())>>::type>
#endif
: std::true_type {};


Expand Down Expand Up @@ -198,19 +213,28 @@ implements_struct_begin_with_base

template <typename Input> struct
implements_struct_begin<Input,
typename boost::enable_if<bond::check_method<void (Input::*)(), &Input::ReadStructBegin> >::type>
#ifdef BOND_NO_SFINAE_EXPR
typename boost::enable_if<check_method<void (Input::*)(), &Input::ReadStructBegin> >::type>
#else
detail::mpl::void_t<decltype(std::declval<Input>().ReadStructBegin())>>
#endif
: std::true_type {};


template <typename Input> struct
implements_struct_begin_with_base<Input,
typename boost::enable_if<bond::check_method<void (Input::*)(bool), &Input::ReadStructBegin> >::type>
#ifdef BOND_NO_SFINAE_EXPR
typename boost::enable_if<check_method<void (Input::*)(bool), &Input::ReadStructBegin> >::type>
#else
detail::mpl::void_t<decltype(std::declval<Input>().ReadStructBegin(std::declval<bool>()))>>
#endif
: std::true_type {};


// StructBegin
template <typename Input>
typename boost::enable_if<implements_struct_begin<Input> >::type
typename boost::enable_if_c<implements_struct_begin<Input>::value
&& !implements_struct_begin_with_base<Input>::value>::type
StructBegin(Input& input, bool /*base*/)
{
return input.ReadStructBegin();
Expand All @@ -234,7 +258,8 @@ StructBegin(Input& /*input*/, bool /*base*/)

// StructEnd
template <typename Input>
typename boost::enable_if<implements_struct_begin<Input> >::type
typename boost::enable_if_c<implements_struct_begin<Input>::value
&& !implements_struct_begin_with_base<Input>::value>::type
StructEnd(Input& input, bool /*base*/)
{
return input.ReadStructEnd();
Expand Down
10 changes: 8 additions & 2 deletions cpp/inc/bond/core/reflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,15 @@ template <typename T, typename Enable = void> struct
is_writer
: std::false_type {};


template <typename T> struct
is_writer<T, typename boost::enable_if<check_method<void (T::*)(const Metadata&, bool), &T::WriteStructBegin> >::type>
is_writer<T,
#ifdef BOND_NO_SFINAE_EXPR
typename boost::enable_if<check_method<void (T::*)(const Metadata&, bool), &T::WriteStructBegin> >::type>
#else
detail::mpl::void_t<decltype(std::declval<T>().WriteStructBegin(
std::declval<Metadata>(),
std::declval<bool>()))>>
#endif
: std::true_type {};


Expand Down
1 change: 1 addition & 0 deletions cpp/inc/bond/core/traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ get_protocol_writer<Reader<Input, MarshaledBondedProtocols>, Output>
};


// Used only for older compilers for which BOND_NO_SFINAE_EXPR is defined.
template <typename T, T> struct
check_method
: std::true_type {};
Expand Down
14 changes: 12 additions & 2 deletions cpp/inc/bond/protocol/encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ implements_varint_write


template <typename Buffer, typename T> struct
implements_varint_write<Buffer, T, typename boost::enable_if<bond::check_method<void (Buffer::*)(T), &Buffer::WriteVariableUnsigned> >::type>
implements_varint_write<Buffer, T,
#ifdef BOND_NO_SFINAE_EXPR
typename boost::enable_if<check_method<void (Buffer::*)(T), &Buffer::WriteVariableUnsigned> >::type>
#else
detail::mpl::void_t<decltype(std::declval<Buffer>().WriteVariableUnsigned(std::declval<T>()))>>
#endif
: std::true_type {};


Expand Down Expand Up @@ -73,7 +78,12 @@ implements_varint_read


template <typename Buffer, typename T> struct
implements_varint_read<Buffer, T, typename boost::enable_if<bond::check_method<void (Buffer::*)(T&), &Buffer::ReadVariableUnsigned> >::type>
implements_varint_read<Buffer, T,
#ifdef BOND_NO_SFINAE_EXPR
typename boost::enable_if<check_method<void (Buffer::*)(T&), &Buffer::ReadVariableUnsigned> >::type>
#else
detail::mpl::void_t<decltype(std::declval<Buffer>().ReadVariableUnsigned(std::declval<T&>()))>>
#endif
: std::true_type {};


Expand Down

0 comments on commit b3ffdd5

Please sign in to comment.