The following code causes an assert on a recent svn g++, with -std=c++0x. On g++ 4.4 it produces an error. I believe the code to be valid, but am not 100% positive. #include <vector> struct Range { int lb; int ub; Range(int i, int j) : lb(i), ub(j) {} Range(const Range& r) = default; Range() = default; }; template<class T> T deref(const T& t) { return t; } template <class T, template <typename T, typename...> class Cont, class... Args> auto deref(const Cont<T>& u, int i, Args... args) -> decltype(deref(u[i], args...)) { deref(u[i], args...); } template <class T, template <typename T, typename...> class Cont, class... Args> auto deref(const Cont<T>& u, Range r, Args... args) -> Cont<decltype(deref(u[0], args...))> { typedef decltype(deref(u[0], args...)) member; Cont<member> retval; for(int i = r.lb; i <= r.ub; ++i) { retval.push_back(deref(u[i], args...)); } return retval; } int main(void) { std::vector<std::vector<std::vector<int>>> v; int i = deref(v, 1,2,3); std::vector<int> j = deref(v, 1, Range(1,2), 3); }
If you could reduce it somewhat, it would be appreciated. Let's add Jason in CC.
Reduced testcase: template<class T> struct Container { T f() const; }; template<class T> T deref(const T& t) { return t; } template <class T, class... Args> auto deref(const T& u, int r, Args... args) -> decltype(deref(u.f(), args...)) { return deref(u.f(), args...); } int main(void) { Container<Container<int>> v; deref(v,1,2); }
Thanks Chris.
4.4 ICEs for me: > g++-4.4 -S t.C -std=c++0x t.C: In function ‘int main()’: t.C:12: internal compiler error: in tsubst_copy, at cp/pt.c:10077 Please submit a full bug report, with preprocessed source if appropriate. See <http://bugs.opensuse.org/> for instructions.
Subject: Bug 43382 Author: jason Date: Wed May 26 15:00:02 2010 New Revision: 159873 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=159873 Log: PR c++/43382 * pt.c (fn_type_unification): Don't get confused by recursive unification. Added: trunk/gcc/testsuite/g++.dg/cpp0x/variadic101.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/pt.c trunk/gcc/testsuite/ChangeLog
Subject: Bug 43382 Author: jason Date: Wed May 26 15:18:46 2010 New Revision: 159875 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=159875 Log: PR c++/43382 * pt.c (fn_type_unification): Don't get confused by recursive unification. Added: branches/gcc-4_5-branch/gcc/testsuite/g++.dg/cpp0x/variadic101.C Modified: branches/gcc-4_5-branch/gcc/cp/ChangeLog branches/gcc-4_5-branch/gcc/cp/pt.c branches/gcc-4_5-branch/gcc/testsuite/ChangeLog
Fixed for 4.5.1.
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:a3a4f6be0c7ac1536c4d1def14217840b04dd488 commit r10-7835-ga3a4f6be0c7ac1536c4d1def14217840b04dd488 Author: Patrick Palka <ppalka@redhat.com> Date: Mon Apr 20 18:34:00 2020 -0400 c++: Recursive unification with packs and explicit targs [PR94628] This PR seems to be similar to PR c++/43382, except that the recursive call to the variadic function with trailing return type in this testcase is additionally given some explicit template arguments. In the first testcase below, when resolving the recursive call to 'select', fn_type_unification first substitutes in the call's explicit template arguments before doing unification, and so during this substitution the template argument pack for Args is incomplete. Since the pack is incomplete, the substitution of 'args...' in the trailing return type decltype(f(args...)) is handled by the unsubstituted_packs case of tsubst_pack_expansion. But the handling of this case happens _before_ we reset local_specializations, and so the substitution ends up reusing the old binding for 'args' from local_specializations rather than building a new one. This patch fixes this issue by setting up local_specializations sooner in tsubst_pack_expansion, before the handling of the unsubstituted_packs case. It also adds a new policy to local_specialization_stack so that we could use the class here to conditionally replace local_specializations. gcc/cp/ChangeLog: PR c++/94628 * cp-tree.h (lss_policy::lss_nop): New enumerator. * pt.c (local_specialization_stack::local_specialization_stack): Handle an lss_nop policy. (local_specialization_stack::~local_specialization_stack): Likewise. (tsubst_pack_expansion): Use a local_specialization_stack instead of manually saving and restoring local_specializations. Conditionally replace local_specializations sooner, before the handling of the unsubstituted_packs case. gcc/testsuite/ChangeLog: PR c++/94628 * g++.dg/cpp0x/variadic179.C: New test. * g++.dg/cpp0x/variadic180.C: New test.