forked from OSchip/llvm-project
Implement the part of C++0x [temp.arg.explicit]p3 that pertains to
parameter packs. In particular, a parameter pack not otherwise deduced is deduced to an empty parameter pack. The C++0x wording here is a bit unfortunate; this should really only apply to function templates, and it mentions "trailing" parameter packs, which doesn't really make sense in the context of function templates. Will file a core issue separately. llvm-svn: 122463
This commit is contained in:
parent
18b762a946
commit
ca4d91d9f6
|
@ -1708,9 +1708,10 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
|||
// [...] or if any template argument remains neither deduced nor
|
||||
// explicitly specified, template argument deduction fails.
|
||||
llvm::SmallVector<TemplateArgument, 4> Builder;
|
||||
for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
|
||||
for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
|
||||
// FIXME: Variadic templates. Unwrap argument packs?
|
||||
NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I);
|
||||
|
||||
if (!Deduced[I].isNull()) {
|
||||
if (I < NumExplicitlySpecified) {
|
||||
// We have already fully type-checked and converted this
|
||||
|
@ -1777,6 +1778,15 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
|||
|
||||
continue;
|
||||
}
|
||||
|
||||
// C++0x [temp.arg.explicit]p3:
|
||||
// A trailing template parameter pack (14.5.3) not otherwise deduced will
|
||||
// be deduced to an empty sequence of template arguments.
|
||||
// FIXME: Where did the word "trailing" come from?
|
||||
if (Param->isTemplateParameterPack()) {
|
||||
Builder.push_back(TemplateArgument(0, 0));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Substitute into the default template argument, if available.
|
||||
TemplateArgumentLoc DefArg
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
|
||||
|
||||
namespace ParameterPacksWithFunctions {
|
||||
template<typename ...> struct count;
|
||||
|
||||
template<typename Head, typename ...Tail>
|
||||
struct count<Head, Tail...> {
|
||||
static const unsigned value = 1 + count<Tail...>::value;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct count<> {
|
||||
static const unsigned value = 0;
|
||||
};
|
||||
|
||||
template<unsigned> struct unsigned_c { };
|
||||
|
||||
template<typename ... Types>
|
||||
unsigned_c<count<Types...>::value> f();
|
||||
|
||||
void test_f() {
|
||||
unsigned_c<0> uc0a = f(); // okay, deduced to an empty pack
|
||||
unsigned_c<0> uc0b = f<>();
|
||||
unsigned_c<1> uc1 = f<int>();
|
||||
unsigned_c<2> uc2 = f<float, double>();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue