From 6bd1d4090a93820538af4235e24f187ec77ea49d Mon Sep 17 00:00:00 2001 From: Peter Griess Date: Wed, 25 Sep 2013 21:07:50 -0500 Subject: [PATCH] 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 --- folly/Conv.h | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/folly/Conv.h b/folly/Conv.h index 28ad844b..75c243c4 100644 --- a/folly/Conv.h +++ b/folly/Conv.h @@ -122,6 +122,23 @@ typename std::tuple_element< 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 +struct last_element { + typedef typename std::enable_if< + sizeof...(Ts) >= 1, + typename std::tuple_element< + sizeof...(Ts) - 1, std::tuple + >::type>::type type; +}; + +template <> +struct last_element<> { + typedef void type; +}; + } // namespace detail /******************************************************************************* @@ -459,9 +476,8 @@ template typename std::enable_if= 2 && detail::IsSomeString< typename std::remove_pointer< - typename std::tuple_element< - sizeof...(Ts) - 1, std::tuple - >::type>::type>::value>::type + typename detail::last_element::type + >::type>::value>::type toAppend(const T& v, const Ts&... vs) { toAppend(v, detail::getLastElement(vs...)); toAppend(vs...); @@ -499,9 +515,8 @@ template typename std::enable_if= 2 && detail::IsSomeString< typename std::remove_pointer< - typename std::tuple_element< - sizeof...(Ts) - 1, std::tuple - >::type>::type>::value>::type + typename detail::last_element::type + >::type>::value>::type toAppendDelim(const Delimiter& delim, const T& v, const Ts&... vs) { toAppend(v, delim, detail::getLastElement(vs...)); toAppendDelim(delim, vs...); -- 2.34.1