Commit 6bd1d409 authored by Peter Griess's avatar Peter Griess

Avoid static_assert in tuple_element for Clang/libc++

Summary:
- Clang/libc++ has a static_assert that blows when tuple_element is
invoked with a tuple of length 0. Unfortunately if we embed this
construct in an enable_if, it still gets evaluated. To work around
this, wrap this in a last_element struct and specialize the 0-element
case there explicitly.

Test Plan:
- fbconfig -r folly && fbmake runtests
- ./configure && make check on Ubuntu/FC/Mac

Reviewed By: andrei.alexandrescu@fb.com

FB internal diff: D998591
parent 3b3fa008
...@@ -122,6 +122,23 @@ typename std::tuple_element< ...@@ -122,6 +122,23 @@ typename std::tuple_element<
return getLastElement(vs...); return getLastElement(vs...);
} }
// This class exists to specialize away std::tuple_element in the case where we
// have 0 template arguments. Without this, Clang/libc++ will blow a
// static_assert even if tuple_element is protected by an enable_if.
template <class... Ts>
struct last_element {
typedef typename std::enable_if<
sizeof...(Ts) >= 1,
typename std::tuple_element<
sizeof...(Ts) - 1, std::tuple<Ts...>
>::type>::type type;
};
template <>
struct last_element<> {
typedef void type;
};
} // namespace detail } // namespace detail
/******************************************************************************* /*******************************************************************************
...@@ -459,9 +476,8 @@ template <class T, class... Ts> ...@@ -459,9 +476,8 @@ template <class T, class... Ts>
typename std::enable_if<sizeof...(Ts) >= 2 typename std::enable_if<sizeof...(Ts) >= 2
&& detail::IsSomeString< && detail::IsSomeString<
typename std::remove_pointer< typename std::remove_pointer<
typename std::tuple_element< typename detail::last_element<Ts...>::type
sizeof...(Ts) - 1, std::tuple<Ts...> >::type>::value>::type
>::type>::type>::value>::type
toAppend(const T& v, const Ts&... vs) { toAppend(const T& v, const Ts&... vs) {
toAppend(v, detail::getLastElement(vs...)); toAppend(v, detail::getLastElement(vs...));
toAppend(vs...); toAppend(vs...);
...@@ -499,9 +515,8 @@ template <class Delimiter, class T, class... Ts> ...@@ -499,9 +515,8 @@ template <class Delimiter, class T, class... Ts>
typename std::enable_if<sizeof...(Ts) >= 2 typename std::enable_if<sizeof...(Ts) >= 2
&& detail::IsSomeString< && detail::IsSomeString<
typename std::remove_pointer< typename std::remove_pointer<
typename std::tuple_element< typename detail::last_element<Ts...>::type
sizeof...(Ts) - 1, std::tuple<Ts...> >::type>::value>::type
>::type>::type>::value>::type
toAppendDelim(const Delimiter& delim, const T& v, const Ts&... vs) { toAppendDelim(const Delimiter& delim, const T& v, const Ts&... vs) {
toAppend(v, delim, detail::getLastElement(vs...)); toAppend(v, delim, detail::getLastElement(vs...));
toAppendDelim(delim, vs...); toAppendDelim(delim, vs...);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment