Work around yet another MSVC 2015 SFINAE bug.

Although we defined a CBS -> Span<const uint8_t> conversion, MSVC 2015
keeps trying to call the Span(const Container&) constructor. It seems to
not correctly SFINAE the existence of data() and size() members unless
the expression is inlined into the default template argument.

Change-Id: I4e88f820b78ce72ad1b014b5bae0830bc7d099d4
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48945
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/span.h b/include/openssl/span.h
index 6b1b232..79f1d41 100644
--- a/include/openssl/span.h
+++ b/include/openssl/span.h
@@ -94,18 +94,6 @@
 template <typename T>
 class Span : private internal::SpanBase<const T> {
  private:
-  // 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 = std::enable_if<
-      std::is_convertible<decltype(std::declval<C>().data()), T *>::value &&
-      std::is_integral<decltype(std::declval<C>().size())>::value>;
-
   static const size_t npos = static_cast<size_t>(-1);
 
  public:
@@ -116,12 +104,27 @@
   constexpr Span(T (&array)[N]) : Span(array, N) {}
 
   template <
-      typename C, typename = typename EnableIfContainer<C>::type,
+      typename C,
+      // 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.
+      //
+      // TODO(davidben): Move this and the identical copy below into an
+      // EnableIfContainer alias when we drop MSVC 2015 support. MSVC 2015's
+      // SFINAE support cannot handle type aliases.
+      typename = typename std::enable_if<
+          std::is_convertible<decltype(std::declval<C>().data()), T *>::value &&
+          std::is_integral<decltype(std::declval<C>().size())>::value>::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 = typename EnableIfContainer<C>::type,
+      typename C,
+      typename = typename std::enable_if<
+          std::is_convertible<decltype(std::declval<C>().data()), T *>::value &&
+          std::is_integral<decltype(std::declval<C>().size())>::value>::type,
       typename = typename std::enable_if<!std::is_const<T>::value, C>::type>
   explicit Span(C &container)
       : data_(container.data()), size_(container.size()) {}