Info.PendingDeducedPacks[Pack.Index] = Pack.Outer;
}
+ /// Determine whether this pack has already been partially expanded into a
+ /// sequence of (prior) function parameters / template arguments.
+ bool isPartiallyExpanded() {
+ if (Packs.size() != 1 || !S.CurrentInstantiationScope)
+ return false;
+
+ auto *PartiallySubstitutedPack =
+ S.CurrentInstantiationScope->getPartiallySubstitutedPack();
+ return PartiallySubstitutedPack &&
+ getDepthAndIndex(PartiallySubstitutedPack) ==
+ std::make_pair(Info.getDeducedDepth(), Packs.front().Index);
+ }
+
/// Move to deducing the next element in each pack that is being deduced.
void nextPackElement() {
// Capture the deduced template arguments for each parameter pack expanded
return false;
}
+static void
+MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
+ bool OnlyDeduced,
+ unsigned Level,
+ llvm::SmallBitVector &Deduced);
+
/// \brief Substitute the explicitly-provided template arguments into the
/// given function template according to C++ [temp.arg.explicit].
///
// Enter a new template instantiation context where we check the
// explicitly-specified template arguments against this function template,
// and then substitute them into the function parameter types.
- SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end());
+ SmallVector<TemplateArgument, 4> DeducedArgs;
InstantiatingTemplate Inst(*this, Info.getLocation(), FunctionTemplate,
DeducedArgs,
ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution,
// Template argument deduction is done by comparing each function template
// parameter type (call it P) with the type of the corresponding argument
// of the call (call it A) as described below.
- unsigned CheckArgs = Args.size();
if (Args.size() < Function->getMinRequiredArguments() && !PartialOverloading)
return TDK_TooFewArguments;
else if (TooManyArguments(NumParams, Args.size(), PartialOverloading)) {
= Function->getType()->getAs<FunctionProtoType>();
if (Proto->isTemplateVariadic())
/* Do nothing */;
- else if (Proto->isVariadic())
- CheckArgs = NumParams;
- else
+ else if (!Proto->isVariadic())
return TDK_TooManyArguments;
}
dyn_cast<PackExpansionType>(ParamType);
if (!ParamExpansion) {
// Simple case: matching a function parameter to a function argument.
- if (ArgIdx >= CheckArgs)
+ if (ArgIdx >= Args.size())
break;
if (auto Result = DeduceCallArgument(ParamType, ArgIdx++))
continue;
}
+ QualType ParamPattern = ParamExpansion->getPattern();
+ PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info,
+ ParamPattern);
+
// C++0x [temp.deduct.call]p1:
// For a function parameter pack that occurs at the end of the
// parameter-declaration-list, the type A of each remaining argument of
// the call is compared with the type P of the declarator-id of the
// function parameter pack. Each comparison deduces template arguments
// for subsequent positions in the template parameter packs expanded by
- // the function parameter pack. For a function parameter pack that does
- // not occur at the end of the parameter-declaration-list, the type of
- // the parameter pack is a non-deduced context.
- // FIXME: This does not say that subsequent parameters are also non-deduced.
- // See also DR1388 / DR1399, which effectively says we should keep deducing
- // after the pack.
- if (ParamIdx + 1 < NumParamTypes)
- break;
-
- QualType ParamPattern = ParamExpansion->getPattern();
- PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info,
- ParamPattern);
-
- for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx)
- if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx))
- return Result;
+ // the function parameter pack. When a function parameter pack appears
+ // in a non-deduced context [not at the end of the list], the type of
+ // that parameter pack is never deduced.
+ //
+ // FIXME: The above rule allows the size of the parameter pack to change
+ // after we skip it (in the non-deduced case). That makes no sense, so
+ // we instead notionally deduce the pack against N arguments, where N is
+ // the length of the explicitly-specified pack if it's expanded by the
+ // parameter pack and 0 otherwise, and we treat each deduction as a
+ // non-deduced context.
+ if (ParamIdx + 1 == NumParamTypes) {
+ for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx)
+ if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx))
+ return Result;
+ } else {
+ // If the parameter type contains an explicitly-specified pack that we
+ // could not expand, skip the number of parameters notionally created
+ // by the expansion.
+ Optional<unsigned> NumExpansions = ParamExpansion->getNumExpansions();
+ if (NumExpansions && !PackScope.isPartiallyExpanded())
+ for (unsigned I = 0; I != *NumExpansions && ArgIdx < Args.size();
+ ++I, ++ArgIdx)
+ // FIXME: Should we add OriginalCallArgs for these? What if the
+ // corresponding argument is a list?
+ PackScope.nextPackElement();
+ }
// Build argument packs for each of the parameter packs expanded by this
// pack expansion.
if (auto Result = PackScope.finish())
return Result;
-
- // After we've matching against a parameter pack, we're done.
- break;
}
return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
return StillUndeduced;
}
-static void
-MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
- bool OnlyDeduced,
- unsigned Level,
- llvm::SmallBitVector &Deduced);
-
/// \brief If this is a non-static member function,
static void
AddImplicitObjectParameterType(ASTContext &Context,
constexpr Y y = Y(); // expected-error {{no matching}}
#endif
}
+
+namespace dr1388 { // dr1388: 4.0
+ template<typename A, typename ...T> void f(T..., A); // expected-note 1+{{candidate}} expected-error 0-1{{C++11}}
+ template<typename ...T> void g(T..., int); // expected-note 1+{{candidate}} expected-error 0-1{{C++11}}
+ template<typename ...T, typename A> void h(T..., A); // expected-note 1+{{candidate}} expected-error 0-1{{C++11}}
+
+ void test_f() {
+ f(0); // ok, trailing parameter pack deduced to empty
+ f(0, 0); // expected-error {{no matching}}
+ f<int>(0);
+ f<int>(0, 0); // expected-error {{no matching}}
+ f<int, int>(0, 0);
+ f<int, int, int>(0, 0); // expected-error {{no matching}}
+
+ g(0);
+ g(0, 0); // expected-error {{no matching}}
+ g<>(0);
+ g<int>(0); // expected-error {{no matching}}
+ g<int>(0, 0);
+
+ h(0);
+ h(0, 0); // expected-error {{no matching}}
+ h<int>(0, 0);
+ h<int, int>(0, 0); // expected-error {{no matching}}
+ }
+
+ // A non-trailing parameter pack is still a non-deduced context, even though
+ // we know exactly how many arguments correspond to it.
+ template<typename T, typename U> struct pair {};
+ template<typename ...T> struct tuple { typedef char type; }; // expected-error 0-2{{C++11}}
+ template<typename ...T, typename ...U> void f_pair_1(pair<T, U>..., int); // expected-error 0-2{{C++11}} expected-note {{different lengths (2 vs. 0)}}
+ template<typename ...T, typename U> void f_pair_2(pair<T, char>..., U); // expected-error 0-2{{C++11}}
+ template<typename ...T, typename ...U> void f_pair_3(pair<T, U>..., tuple<U...>); // expected-error 0-2{{C++11}} expected-note {{different lengths (2 vs. 1)}}
+ template<typename ...T> void f_pair_4(pair<T, char>..., T...); // expected-error 0-2{{C++11}} expected-note {{<int, long> vs. <int, long, const char *>}}
+ void g(pair<int, char> a, pair<long, char> b, tuple<char, char> c) {
+ f_pair_1<int, long>(a, b, 0); // expected-error {{no match}}
+ f_pair_2<int, long>(a, b, 0);
+ f_pair_3<int, long>(a, b, c);
+ f_pair_3<int, long>(a, b, tuple<char>()); // expected-error {{no match}}
+ f_pair_4<int, long>(a, b, 0, 0L);
+ f_pair_4<int, long>(a, b, 0, 0L, "foo"); // expected-error {{no match}}
+ }
+}
+
+namespace dr1399 { // dr1399: dup 1388
+ template<typename ...T> void f(T..., int, T...) {} // expected-note {{candidate}} expected-error 0-1{{C++11}}
+ void g() {
+ f(0);
+ f<int>(0, 0, 0);
+ f(0, 0, 0); // expected-error {{no match}}
+ }
+}
first_arg_pair(make_pair(ip, 17), 16); // expected-error{{no matching function for call to 'first_arg_pair'}}
}
-// For a function parameter pack that does not occur at the end of the
-// parameter-declaration-list, the type of the parameter pack is a
-// non-deduced context.
+// A function parameter pack not at the end of the parameter list is never
+// deduced. We interpret this as meaning the types within it are never
+// deduced, and thus must match explicitly-specified values.
template<typename ...Types> struct tuple { };
template<typename ...Types>
-void pack_not_at_end(tuple<Types...>, Types... values, int);
+void pack_not_at_end(tuple<Types...>, Types... values, int); // expected-note {{<int *, double *> vs. <>}}
void test_pack_not_at_end(tuple<int*, double*> t2) {
- pack_not_at_end(t2, 0, 0, 0);
+ pack_not_at_end(t2, 0, 0, 0); // expected-error {{no match}}
+ // FIXME: Should the "original argument type must match deduced parameter
+ // type" rule apply here?
+ pack_not_at_end<int*, double*>(t2, 0, 0, 0); // ok
}
}
namespace deduction_after_explicit_pack {
- template<typename ...T, typename U> int *f(T ...t, int &r, U *u) { // expected-note {{couldn't infer template argument 'U'}}
+ template<typename ...T, typename U> int *f(T ...t, int &r, U *u) {
return u;
}
template<typename U, typename ...T> int *g(T ...t, int &r, U *u) {
return u;
}
void h(float a, double b, int c) {
- // FIXME: Under DR1388, this appears to be valid.
- f<float&, double&>(a, b, c, &c); // expected-error {{no matching}}
+ f<float&, double&>(a, b, c, &c); // ok
g<int, float&, double&>(a, b, c, &c); // ok
}
+
+ template <typename... T> void i(T..., int, T..., ...); // expected-note 5{{deduced conflicting}}
+ void j() {
+ i(0);
+ i(0, 1); // expected-error {{no match}}
+ i(0, 1, 2); // expected-error {{no match}}
+ i<>(0);
+ i<>(0, 1); // expected-error {{no match}}
+ i<>(0, 1, 2); // expected-error {{no match}}
+ i<int, int>(0, 1, 2, 3, 4);
+ i<int, int>(0, 1, 2, 3, 4, 5); // expected-error {{no match}}
+ }
+
+ // GCC alarmingly accepts this by deducing T={int} by matching the second
+ // parameter against the first argument, then passing the first argument
+ // through the first parameter.
+ template<typename... T> struct X { X(int); operator int(); };
+ template<typename... T> void p(T..., X<T...>, ...); // expected-note {{deduced conflicting}}
+ void q() { p(X<int>(0), 0); } // expected-error {{no match}}
}
namespace overload_vs_pack {
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1388">1388</a></td>
<td>CD3</td>
<td>Missing non-deduced context following a function parameter pack</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">SVN</td>
</tr>
<tr id="1389">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1389">1389</a></td>
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1399">1399</a></td>
<td>CD3</td>
<td>Deduction with multiple function parameter packs</td>
- <td class="none" align="center">Unknown</td>
+ <td class="svn" align="center">Duplicate of <a href="#1388">1388</a></td>
</tr>
<tr id="1400">
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1400">1400</a></td>