+2013-05-16 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/56782 - Regression with empty pack expansions
+ * pt.c (use_pack_expansion_extra_args_p): When at least a
+ parameter pack has an empty argument pack, and another parameter
+ pack has no argument pack at all, use the PACK_EXPANSION_EXTRA
+ mechanism.
+
2013-05-15 Paolo Carlini <paolo.carlini@oracle.com>
* name-lookup.c (pushdecl_maybe_friend_1): Replace pairs of
int arg_pack_len,
bool has_empty_arg)
{
+ /* If one pack has an expansion and another pack has a normal
+ argument or if one pack has an empty argument and an another
+ one hasn't then tsubst_pack_expansion cannot perform the
+ substitution and need to fall back on the
+ PACK_EXPANSION_EXTRA mechanism. */
if (parm_packs == NULL_TREE)
return false;
+ else if (has_empty_arg)
+ return true;
bool has_expansion_arg = false;
for (int i = 0 ; i < arg_pack_len; ++i)
has_non_expansion_arg = true;
}
- /* If one pack has an expansion and another pack has a normal
- argument or if one pack has an empty argument another one
- hasn't then tsubst_pack_expansion cannot perform the
- substitution and need to fall back on the
- PACK_EXPANSION_EXTRA mechanism. */
- if ((has_expansion_arg && has_non_expansion_arg)
- || (has_empty_arg && (has_expansion_arg || has_non_expansion_arg)))
+ if (has_expansion_arg && has_non_expansion_arg)
return true;
}
return false;
--- /dev/null
+// PR c++/56782
+// { dg-options -std=c++0x }
+
+template<class T>
+T&& declval();
+
+struct is_convertible_impl {
+ template<class T>
+ static void sink(T);
+
+ template<class T, class U, class = decltype(sink<U>(declval<T>()))>
+ static auto test(int) -> char;
+
+ template<class, class>
+ static auto test(...) -> char(&)[2];
+};
+
+template<class T, class U>
+struct is_convertible : is_convertible_impl
+{
+ static const bool value = sizeof(test<T, U>(0)) == 1;
+};
+
+template<bool, class>
+struct enable_if {};
+
+template<class T>
+struct enable_if<true, T> { typedef T type; };
+
+template<bool, class If, class Else>
+struct conditional { typedef If type; };
+
+template<class If, class Else>
+struct conditional<false, If, Else> { typedef Else type; };
+
+template<class...>
+struct and_;
+
+template<>
+struct and_<>
+{
+ static const bool value = true;
+};
+
+template<class P>
+struct and_<P> : P
+{
+};
+
+template<class P1, class P2>
+struct and_<P1, P2> : conditional<P1::value, P2, P1>::type
+{
+};
+
+template<class... T>
+struct Tuple {
+ template<class... U,
+ class = typename enable_if<and_<is_convertible<U, T>... >::value, int>::type
+ >
+ Tuple(U&&...){}
+};
+
+static_assert(is_convertible<Tuple<>, Tuple<>>::value, "Ouch"); //#1