[C++] Use std::integral_constant<>

Work around some compiler bugs.
This commit is contained in:
Chad Walters 2017-04-03 16:04:43 -07:00 коммит произвёл Christopher Warrington
Родитель 3809d0acd7
Коммит fd9a186676
10 изменённых файлов: 136 добавлений и 172 удалений

Просмотреть файл

@ -15,7 +15,7 @@ different versioning scheme, following the Haskell community's
* `gbc` & compiler library: TBD (major bump needed)
* IDL core version: TBD
* IDL comm version: TBD
* C++ version: TBD (minor bump needed)
* C++ version: TBD (major bump needed)
* C# NuGet version: TBD (minor bump needed)
* C# Comm NuGet version: TBD (minor bump needed)
@ -38,6 +38,11 @@ different versioning scheme, following the Haskell community's
### C++ ###
* **Breaking change** A C++11 compiler is now required. The minimum
supported C++ compiler versions are now:
* Clang 3.4 or newer
* GNU C++ 4.7 or newer
* Microsoft Visual C++ 2013 or newer
* Fix Python shared_ptr converter build break with Boost 1.63.
* Improve compliance with
[Microsoft's SDL](https://www.microsoft.com/en-us/sdl/).

Просмотреть файл

@ -40,10 +40,10 @@ git clone --recursive https://github.com/Microsoft/bond.git
```
In order to build Bond you will need CMake (3.1+), Haskell (ghc 7.4+ and
cabal-install 1.18+) and Boost (1.58+). The core Bond C++ library can be used
with C++03 compilers, although Bond Comm, Python support, unit tests and various
examples require some C++11 features. (Note: Boost 1.59 may not work with
Bond Comm due to some bugs in that version of the Boost ASIO library).
cabal-install 1.18+) and Boost (1.58+). Bond's C++ library requires some
C++11 features (currently limited to those supported bv Visual C++ 2013).
(Note: Boost 1.59 may not work with Bond Comm due to some bugs in that
version of the Boost ASIO library).
Following are specific instructions for building on various platforms.
@ -235,12 +235,7 @@ cmake -G "Visual Studio 14 2015 Win64" ..
Setting `PreferredToolArchitecture=x64` selects the 64-bit toolchain which
dramatically improves build speed. (The Bond unit tests are too big to build
with 32-bit tools.) This variable works for Visual Studio 2013 or 2015. For
Visual Studio 2012 set the following environment variable instead:
```bash
set _IsNativeEnvironment=true
```
with 32-bit tools.)
Instead of `cmake` you can also use `cmake-gui` and specify configuration
settings in the UI. This configuration step has to be performed only once. From

Просмотреть файл

@ -49,7 +49,7 @@ class To;
template <typename T, typename Enable = void> struct
schema_for_passthrough;
template<typename T> struct
template<typename T, typename Enable = void> struct
get_type_id;
template <typename T> struct

Просмотреть файл

@ -16,10 +16,9 @@ namespace bond
template <typename T, typename Reader, typename Unused = void> struct
is_marshaled_bonded
{
static const bool value = uses_marshaled_bonded<Reader, Unused>::value
&& is_bonded<T>::value;
};
: std::integral_constant<bool,
uses_marshaled_bonded<Reader, Unused>::value
&& is_bonded<T>::value> {};
template <typename T, typename Buffer, typename Transform>

Просмотреть файл

@ -24,31 +24,22 @@ namespace detail
template <typename T, typename Enable = void> struct
hierarchy_depth
{
static const uint16_t value = 1;
};
: std::integral_constant<uint16_t, 1> {};
template <typename T> struct
hierarchy_depth<T, typename boost::enable_if<is_class<typename schema<typename T::base>::type> >::type>
{
static const uint16_t value = 1 + hierarchy_depth<typename schema<typename T::base>::type>::value;
};
: std::integral_constant<uint16_t, 1 + hierarchy_depth<typename schema<typename T::base>::type>::value> {};
template <typename T> struct
expected_depth
{
static const uint16_t value = 0xffff;
};
: std::integral_constant<uint16_t, 0xffff> {};
template <typename T> struct
expected_depth<bond::To<T> >
{
static const uint16_t value = hierarchy_depth<typename schema<T>::type>::value;
};
: hierarchy_depth<typename schema<T>::type> {};
template <typename Input, typename T = void, typename Enable = void> struct
is_reader

Просмотреть файл

@ -256,10 +256,8 @@ StructEnd(Input& /*input*/, bool /*base*/)
// and for untagged protocols which implement field omitting support.
template <typename T> struct
may_omit_fields
{
static const bool value = !uses_static_parser<typename T::Reader>::value
|| detail::implements_field_omitting<T>::value;
};
: std::integral_constant<bool,
!uses_static_parser<typename T::Reader>::value
|| detail::implements_field_omitting<T>::value> {};
} // namespace bond

Просмотреть файл

@ -20,14 +20,13 @@ namespace detail
template <typename T> struct
use_value
{
static const bool value = is_list_container<T>::value
|| is_set_container<T>::value
|| is_map_container<T>::value
|| is_string<T>::value
|| is_wstring<T>::value
|| !is_class<T>::value;
};
: std::integral_constant<bool,
is_list_container<T>::value
|| is_set_container<T>::value
|| is_map_container<T>::value
|| is_string<T>::value
|| is_wstring<T>::value
|| !is_class<T>::value> {};
template<typename T, typename E = void> struct
has_compare

Просмотреть файл

@ -50,22 +50,13 @@ typedef std::map<std::string, std::string> Attributes;
// field is required
struct required_field_modifier
{
static const bond::Modifier value = bond::Required;
};
using required_field_modifier = std::integral_constant<bond::Modifier, bond::Required>;
// field is optional
struct optional_field_modifier
{
static const bond::Modifier value = bond::Optional;
};
using optional_field_modifier = std::integral_constant<bond::Modifier, bond::Optional>;
// field is required optional
struct required_optional_field_modifier
{
static const bond::Modifier value = bond::RequiredOptional;
};
using required_optional_field_modifier = std::integral_constant<bond::Modifier, bond::RequiredOptional>;
/// @brief Field description in compile-time schema
@ -328,15 +319,12 @@ const reflection::nothing nothing = {};
template <typename T, typename Iter> struct
field_id
{
static const uint16_t value = boost::mpl::deref<Iter>::type::id;
};
: std::integral_constant<uint16_t, boost::mpl::deref<Iter>::type::id> {};
template <typename T> struct
field_id<T, typename boost::mpl::end<T>::type>
{
static const uint16_t value = invalid_field_id;
};
: std::integral_constant<uint16_t, invalid_field_id> {};
template <typename T, uint16_t minId = 0> struct
next_required_field
@ -344,10 +332,9 @@ next_required_field
private:
template <typename Field> struct
is_next_required
{
static const bool value = Field::id >= minId
&& is_same<typename Field::field_modifier, typename reflection::required_field_modifier>::value;
};
: std::integral_constant<bool,
Field::id >= minId
&& std::is_same<typename Field::field_modifier, typename reflection::required_field_modifier>::value> {};
public:
static const uint16_t value = field_id<T, typename boost::mpl::find_if<T, is_next_required<_> >::type>::value;
@ -391,12 +378,9 @@ remove_bonded<bonded<T> >
template <typename T> struct
is_bond_type
{
typedef typename remove_const<T>::type U;
static const bool value = is_bonded<U>::value
|| has_schema<U>::value;
};
: std::integral_constant<bool,
is_bonded<typename std::remove_const<T>::type>::value
|| has_schema<typename std::remove_const<T>::type>::value> {};
struct Unknown;
@ -436,13 +420,10 @@ schema_for_passthrough<T, typename boost::disable_if<has_schema<typename remove_
template <typename T> struct
is_container
{
typedef typename remove_const<T>::type U;
static const bool value = is_list_container<U>::value
|| is_set_container<U>::value
|| is_map_container<U>::value;
};
: std::integral_constant<bool,
is_list_container<typename std::remove_const<T>::type>::value
|| is_set_container<typename std::remove_const<T>::type>::value
|| is_map_container<typename std::remove_const<T>::type>::value> {};
template <typename Field, typename Transform, typename Enable = void> struct
@ -473,14 +454,12 @@ is_matching_container
template <typename T1, typename T2> struct
is_matching_basic
{
static const bool value =
(is_string<T1>::value && is_string<T2>::value)
: std::integral_constant<bool,
(is_string<T1>::value && is_string<T2>::value)
|| (is_wstring<T1>::value && is_wstring<T2>::value)
|| ((sizeof(T1) <= sizeof(T2))
&& ((is_unsigned<T1>::value && is_unsigned<T2>::value)
|| (is_signed_int_or_enum<T1>::value && is_signed_int_or_enum<T2>::value)));
};
&& ((is_unsigned<T1>::value && is_unsigned<T2>::value)
|| (is_signed_int_or_enum<T1>::value && is_signed_int_or_enum<T2>::value)))> {};
template <typename T> struct
@ -490,12 +469,10 @@ is_matching_basic<typename aliased_type<T>::type, T>
template <typename T1, typename T2> struct
is_matching
{
static const bool value =
(is_bond_type<T1>::value && is_bond_type<T2>::value)
: std::integral_constant<bool,
(is_bond_type<T1>::value && is_bond_type<T2>::value)
|| (is_matching_basic<T1, T2>::value)
|| (is_matching_container<T1, T2>::value);
};
|| (is_matching_container<T1, T2>::value)> {};
template <typename T> struct
@ -523,7 +500,7 @@ is_matching_basic<float, double>
: true_type {};
template <typename T> struct
template <typename T, typename Enable> struct
get_type_id;
@ -538,10 +515,9 @@ is_matching_container<T1, T2,
// tuples match if the elements match
template <typename T1, typename T2, typename U1, typename U2> struct
is_matching<std::pair<T1, T2>, std::pair<U1, U2> >
{
static const bool value = is_matching<T1, U1>::value
&& is_matching<T2, U2>::value;
};
: std::integral_constant<bool,
is_matching<T1, U1>::value
&& is_matching<T2, U2>::value> {};
template <typename T1, typename T2> struct
@ -573,10 +549,9 @@ is_element_matching<T, X, typename boost::enable_if<is_container<X> >::type>
template <typename X, typename Reader> struct
is_element_matching<value<void, Reader>, X, typename boost::enable_if<is_container<X> >::type>
{
static const bool value = is_bond_type<typename element_type<X>::type>::value
|| is_container<typename element_type<X>::type>::value;
};
: std::integral_constant<bool,
is_bond_type<typename element_type<X>::type>::value
|| is_container<typename element_type<X>::type>::value> {};
template <typename T, typename X, typename Enable = void> struct
@ -591,10 +566,9 @@ is_map_element_matching<T, X, typename boost::enable_if<is_map_container<X> >::t
template <typename X, typename Reader> struct
is_map_element_matching<value<void, Reader>, X, typename boost::enable_if<is_map_container<X> >::type>
{
static const bool value = is_bond_type<typename element_type<X>::type::second_type>::value
|| is_container<typename element_type<X>::type::second_type>::value;
};
: std::integral_constant<bool,
is_bond_type<typename element_type<X>::type::second_type>::value
|| is_container<typename element_type<X>::type::second_type>::value> {};
template <typename T, typename X, typename Enable = void> struct
@ -609,9 +583,8 @@ is_map_key_matching<T, X, typename boost::enable_if<is_map_container<X> >::type>
template <typename T> struct
is_basic_type
{
static const bool value = !(is_container<T>::value || is_bond_type<T>::value);
};
: std::integral_constant<bool,
!(is_container<T>::value || is_bond_type<T>::value)> {};
template <> struct
is_basic_type<void>
@ -625,15 +598,14 @@ is_nested_container
template <typename T> struct
is_nested_container<T, typename boost::enable_if<is_map_container<T> >::type>
{
static const bool value = !is_basic_type<typename element_type<T>::type::second_type>::value;
};
: std::integral_constant<bool,
!is_basic_type<typename element_type<T>::type::second_type>::value> {};
template <typename T> struct
is_nested_container<T, typename boost::enable_if<is_list_container<T> >::type>
{
static const bool value = !is_basic_type<typename element_type<T>::type>::value;
};
: std::integral_constant<bool,
!is_basic_type<typename element_type<T>::type>::value> {};
template <typename T, typename Enable = void> struct
@ -642,18 +614,17 @@ is_struct_container
template <typename T> struct
is_struct_container<T, typename boost::enable_if<is_map_container<T> >::type>
{
static const bool value = has_schema<typename element_type<T>::type::second_type>::value
|| is_struct_container<typename element_type<T>::type::second_type>::value;
};
: std::integral_constant<bool,
has_schema<typename element_type<T>::type::second_type>::value
|| is_struct_container<typename element_type<T>::type::second_type>::value> {};
template <typename T> struct
is_struct_container<T, typename boost::enable_if<is_list_container<T> >::type>
{
static const bool value = has_schema<typename element_type<T>::type>::value
|| is_struct_container<typename element_type<T>::type>::value;
};
: std::integral_constant<bool,
has_schema<typename element_type<T>::type>::value
|| is_struct_container<typename element_type<T>::type>::value> {};
// is_struct_container_field
@ -783,31 +754,31 @@ get_type_id<std::pair<T1, T2> >::value = std::make_pair(
template <> struct
get_type_id<bool>
: boost::integral_constant<BondDataType, BT_BOOL> {};
: std::integral_constant<BondDataType, BT_BOOL> {};
template <> struct
get_type_id<uint8_t>
: boost::integral_constant<BondDataType, BT_UINT8> {};
: std::integral_constant<BondDataType, BT_UINT8> {};
template <> struct
get_type_id<uint16_t>
: boost::integral_constant<BondDataType, BT_UINT16> {};
: std::integral_constant<BondDataType, BT_UINT16> {};
template <> struct
get_type_id<uint32_t>
: boost::integral_constant<BondDataType, BT_UINT32> {};
: std::integral_constant<BondDataType, BT_UINT32> {};
template <> struct
get_type_id<uint64_t>
: boost::integral_constant<BondDataType, BT_UINT64> {};
: std::integral_constant<BondDataType, BT_UINT64> {};
template <> struct
get_type_id<int8_t>
: boost::integral_constant<BondDataType, BT_INT8> {};
: std::integral_constant<BondDataType, BT_INT8> {};
template <> struct
get_type_id<int16_t>
: boost::integral_constant<BondDataType, BT_INT16> {};
: std::integral_constant<BondDataType, BT_INT16> {};
template <> struct
get_type_id<int32_t>
@ -815,11 +786,11 @@ get_type_id<int32_t>
template <> struct
get_type_id<int64_t>
: boost::integral_constant<BondDataType, BT_INT64> {};
: std::integral_constant<BondDataType, BT_INT64> {};
template <> struct
get_type_id<float>
: boost::integral_constant<BondDataType, BT_FLOAT> {};
: std::integral_constant<BondDataType, BT_FLOAT> {};
template <> struct
get_type_id<double>
@ -827,26 +798,40 @@ get_type_id<double>
template <> struct
get_type_id<void>
: boost::integral_constant<BondDataType, BT_UNAVAILABLE> {};
: std::integral_constant<BondDataType, BT_UNAVAILABLE> {};
template <typename T> struct
get_type_id<T, typename boost::enable_if<std::is_enum<T>>::type>
: get_type_id<int32_t> {};
template <typename T> struct
get_type_id<T, typename boost::enable_if<is_bond_type<T>>::type>
: std::integral_constant<BondDataType, BT_STRUCT> {};
template <typename T> struct
get_type_id<T, typename boost::enable_if<is_set_container<typename std::remove_const<T>::type>>::type>
: std::integral_constant<BondDataType, BT_SET> {};
template <typename T> struct
get_type_id<T, typename boost::enable_if<is_map_container<typename std::remove_const<T>::type>>::type>
: std::integral_constant<BondDataType, BT_MAP> {};
template <typename T> struct
get_type_id<T, typename boost::enable_if<is_list_container<typename std::remove_const<T>::type>>::type>
: std::integral_constant<BondDataType, BT_LIST> {};
template <typename T> struct
get_type_id<T, typename boost::enable_if<is_string<typename std::remove_const<T>::type>>::type>
: std::integral_constant<BondDataType, BT_STRING> {};
template <typename T> struct
get_type_id<T, typename boost::enable_if<is_wstring<typename std::remove_const<T>::type>>::type>
: std::integral_constant<BondDataType, BT_WSTRING> {};
template <typename T, typename Enable> struct
get_type_id
{
typedef typename remove_const<T>::type U;
: get_type_id<typename aliased_type<T>::type> {};
static const BondDataType value =
is_enum<T>::value ? get_type_id<int32_t>::value :
is_bond_type<T>::value ? BT_STRUCT :
is_set_container<U>::value ? BT_SET :
is_map_container<U>::value ? BT_MAP :
is_list_container<U>::value ? BT_LIST :
is_string<U>::value ? BT_STRING :
is_wstring<U>::value ? BT_WSTRING :
get_type_id<typename aliased_type<T>::type>::value;
};
template <typename T>
const BondDataType get_type_id<T>::value;
template <typename T> struct
get_list_sub_type_id

Просмотреть файл

@ -36,12 +36,9 @@ is_wstring<std::basic_string<wchar_t, T, A> >
// is_string_type
template <typename T> struct
is_string_type
{
typedef typename remove_const<T>::type U;
static const bool value = is_string<U>::value
|| is_wstring<U>::value;
};
: std::integral_constant<bool,
is_string<typename std::remove_const<T>::type>::value
|| is_wstring<typename std::remove_const<T>::type>::value> {};
// is_list_container<std::list<T, A> >
@ -151,10 +148,9 @@ use_container_allocator_for_elements
template <typename T> struct
use_container_allocator_for_elements<T, typename boost::enable_if<
is_same<typename T::allocator_type::template rebind<int>::other,
typename element_type<T>::type::allocator_type::template rebind<int>::other> >::type>
{
static const bool value = !detail::is_default_allocator<typename T::allocator_type>::value;
};
typename element_type<T>::type::allocator_type::template rebind<int>::other> >::type>
: std::integral_constant<bool,
!detail::is_default_allocator<typename T::allocator_type>::value> {};
template <typename T> struct
use_container_allocator_for_elements<T, typename boost::enable_if_c<
@ -270,12 +266,11 @@ use_map_allocator_for_keys
template <typename T> struct
use_map_allocator_for_keys
<T, typename boost::enable_if<
is_same<typename detail::rebind_allocator<typename T::allocator_type, int>::type,
typename detail::rebind_allocator<typename element_type<T>::type::first_type::allocator_type, int>::type> >::type>
{
static const bool value = !detail::is_default_allocator<typename T::allocator_type>::value;
};
<T, typename boost::enable_if<
is_same<typename detail::rebind_allocator<typename T::allocator_type, int>::type,
typename detail::rebind_allocator<typename element_type<T>::type::first_type::allocator_type, int>::type> >::type>
: std::integral_constant<bool,
!detail::is_default_allocator<typename T::allocator_type>::value> {};
// make_key
@ -308,10 +303,9 @@ use_map_allocator_for_values
template <typename T> struct
use_map_allocator_for_values<T, typename boost::enable_if<
is_same<typename T::allocator_type::template rebind<int>::other,
typename element_type<T>::type::second_type::allocator_type::template rebind<int>::other> >::type>
{
static const bool value = !detail::is_default_allocator<typename T::allocator_type>::value;
};
typename element_type<T>::type::second_type::allocator_type::template rebind<int>::other> >::type>
: std::integral_constant<bool,
!detail::is_default_allocator<typename T::allocator_type>::value> {};
template <typename T> struct
use_map_allocator_for_values<T, typename boost::enable_if_c<

Просмотреть файл

@ -57,20 +57,18 @@ struct is_nothrow_copy_constructible : boost::has_nothrow_copy_constructor<T> {}
// is_signed_int
template <typename T> struct
is_signed_int
{
static const bool value = is_signed<T>::value
&& !is_floating_point<T>::value
&& !is_enum<T>::value;
};
: std::integral_constant<bool,
is_signed<T>::value
&& !is_floating_point<T>::value
&& !is_enum<T>::value> {};
// is_signed_int_or_enum
template <typename T> struct
is_signed_int_or_enum
{
static const bool value = is_signed_int<T>::value
|| is_enum<T>::value;
};
: std::integral_constant<bool,
is_signed_int<T>::value
|| is_enum<T>::value> {};
// schema