Skip to content

Commit

Permalink
#908 message- work-abouts for NVCC SFINAE issues
Browse files Browse the repository at this point in the history
- Usage of decltype for a deleted member in ~some~ SFINAE
  contexts is failing with an error instead of failing
  the substitution.

  Pulling out a pre member check AND using conjunction
  instead of 'and' appears to appears the compiler.
  Neither by themselves is sufficient, nor is moving the
  conjunction inside the has_own_member template sufficient.
  • Loading branch information
pnstickne committed Jul 7, 2020
1 parent 6e35ba7 commit 2bc3c99
Showing 1 changed file with 36 additions and 15 deletions.
51 changes: 36 additions & 15 deletions src/vt/messaging/message/message_serialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,38 @@

namespace vt { namespace messaging {

// C++17 port. ref. https://en.cppreference.com/w/cpp/types/conjunction
template<class...> struct cxx14_conjunction : std::true_type { };
template<class B1> struct cxx14_conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct cxx14_conjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), cxx14_conjunction<Bn...>, B1> {};

// C++17 port. ref. https://en.cppreference.com/w/cpp/types/void_t
template<typename... Ts>
struct cxx14_make_void { typedef void type;};
template<typename... Ts>
using cxx14_void_t = typename cxx14_make_void<Ts...>::type;

// Only some compilers can directly check for a serialization method
// because to do so requires declval on a templated member WITHOUT
// causing templated instantiation (which will fail).
#ifndef vt_quirked_serialize_method_detection

using SerializeSizerType = ::checkpoint::Sizer;

// Covering case work-about for NVCC (CUDA 10.1). See usage site.
template <class T>
struct has_any_serialize_member_t
{
template <typename U>
static auto test(U* u) -> decltype(
u->template serialize<SerializeSizerType>(std::declval<SerializeSizerType&>())
, char(0)) { return char(0); }
static double test(...) { return 0; }
static const bool value = (sizeof(test((T*)0)) == 1);
};

template <typename U, typename = void>
struct has_own_serialize_member_t : std::false_type {};

Expand All @@ -66,7 +93,7 @@ struct has_own_serialize_member_t<U,
std::enable_if_t<
std::is_same<
void (U::*)(::checkpoint::Sizer&),
decltype(&U::template serialize<::checkpoint::Sizer&>)
decltype(&U::template serialize<SerializeSizerType>)
>::value
>>
: std::true_type
Expand All @@ -77,7 +104,14 @@ struct has_own_serialize_member_t<U,
template <typename T>
static constexpr auto const has_own_serialize =
::checkpoint::SerializableTraits<T>::has_serialize_noninstrusive
or has_own_serialize_member_t<T>::value;
// NVCC (CUDA 10.1) does use lazy evaluation with 'and' substituted here.
// The check for has_any.. is also required for NVCC which will
// fail compilation at the decltype usage in has_own.., although
// correctly not-substitute in has_any..
or cxx14_conjunction<
has_any_serialize_member_t<T>,
has_own_serialize_member_t<T>
>::value;

#endif

Expand Down Expand Up @@ -223,19 +257,6 @@ struct is_byte_copyable_t {
};
#endif

// C++17 port. ref. https://en.cppreference.com/w/cpp/types/conjunction
template<class...> struct cxx14_conjunction : std::true_type { };
template<class B1> struct cxx14_conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct cxx14_conjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), cxx14_conjunction<Bn...>, B1> {};

// C++17 port. ref. https://en.cppreference.com/w/cpp/types/void_t
template<typename... Ts>
struct cxx14_make_void { typedef void type;};
template<typename... Ts>
using cxx14_void_t = typename cxx14_make_void<Ts...>::type;

// Foward-declare
struct BaseMsg;

Expand Down

0 comments on commit 2bc3c99

Please sign in to comment.