Fix EnableIfContainer with MSVC 2015.

MSVC 2015's SFINAE implementation is broken. In particular, it seems not
to bother expanding EnableIfContainer unless we force it to by writing
::type. That means we need to use std::enable_if rather than
enable_if_t, even though it's quite wordy.

Change-Id: Ic643ab8a956991bb14af07832be80988f7735428
Reviewed-on: https://boringssl-review.googlesource.com/20764
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Reviewed-by: Martin Kreichgauer <martinkr@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
David Benjamin 2017-09-26 16:12:15 -04:00 committed by CQ bot account: commit-bot@chromium.org
parent 15868b3bba
commit 6666886a9c

View File

@ -92,13 +92,15 @@ class SpanBase {
template <typename T>
class Span : private internal::SpanBase<const T> {
private:
template <bool B, class V = void>
using enable_if_t = typename std::enable_if<B, V>::type;
// Heuristically test whether C is a container type that can be converted into
// a Span by checking for data() and size() member functions.
//
// TODO(davidben): Switch everything to std::enable_if_t when we remove
// support for MSVC 2015. Although we could write our own enable_if_t and MSVC
// 2015 has std::enable_if_t anyway, MSVC 2015's SFINAE implementation is
// problematic and does not work below unless we write the ::type at use.
template <typename C>
using EnableIfContainer = enable_if_t<
using EnableIfContainer = std::enable_if<
std::is_convertible<decltype(std::declval<C>().data()), T *>::value &&
std::is_integral<decltype(std::declval<C>().size())>::value>;
@ -109,12 +111,14 @@ class Span : private internal::SpanBase<const T> {
template <size_t N>
constexpr Span(T (&array)[N]) : Span(array, N) {}
template <typename C, typename = EnableIfContainer<C>,
typename = enable_if_t<std::is_const<T>::value, C>>
template <
typename C, typename = typename EnableIfContainer<C>::type,
typename = typename std::enable_if<std::is_const<T>::value, C>::type>
Span(const C &container) : data_(container.data()), size_(container.size()) {}
template <typename C, typename = EnableIfContainer<C>,
typename = enable_if_t<!std::is_const<T>::value, C>>
template <
typename C, typename = typename EnableIfContainer<C>::type,
typename = typename std::enable_if<!std::is_const<T>::value, C>::type>
explicit Span(C &container)
: data_(container.data()), size_(container.size()) {}