Mam częściowe rozwiązanie, jedynym zastrzeżeniem jest to, że nie mogę dostać std::is_same<N<4>, N<4>>::value
wrócić true
. Cóż, mogę z tym żyć, ponieważ mogłem zdefiniować metodę, która działa bezpośrednio na wartości. Mam jednak nadzieję, że ktoś mógłby udzielić na to poprawnej odpowiedzi.
Położyłem kompletne rozwiązanie i zmodyfikowane dane wejściowe na https://gist.github.com/4178490.
odkryłem, że aby zastąpić argumenty do szablonu klasy i oznacz ją, można by:
- używać argumentów, aby włączyć ClassTemplateDecl do ClassTemplateSpecializationDecl i
- instancję specjalizacja korzystania Metoda Sema::InstantiateClass.
Metoda Sema::RequireCompleteType pośrednio wywołuje InstantiateClass i wymaga mniejszej ilości danych wejściowych, więc nazywam tę metodę zamiast tego. Dlatego chcielibyśmy napisać:
/**
* Instantiate a class template.
*/
ClassTemplateSpecializationDecl* instantiate(ASTContext& ast, Sema& sema,
DeclContext* parent,
ClassTemplateDecl* decl,
ArrayRef<TemplateArgument> args) {
void* ins_point;
auto retval = decl->findSpecialization(args.data(), args.size(), ins_point);
if (retval == nullptr) {
retval = ClassTemplateSpecializationDecl::Create(ast, TTK_Class, parent,
{}, {}, decl,
args.data(), args.size(),
nullptr);
decl->AddSpecialization(retval, ins_point);
}
bool is_incomplete = sema.RequireCompleteType({}, ast.getTypeDeclType(retval),
diag::err_incomplete_type);
return is_incomplete ? nullptr : retval;
}
Ta metoda działa tylko dla ClassTemplateDecl. W pytaniu mamy także TypeAliasTemplateDecl. W tym celu zamierzam bezpośrednio wywołać obiekt TemplateDeclInstantiator, ponieważ jest to jedyny obiekt, który zna TypeAliasTemplateDecl. Być może ta metoda działa również z ClassTemplateDecl, ale nie mogę być pewny, ponieważ wydaje się, że za mało pracy odbywa się za pomocą samego TemplateDeclInstantiator.
/**
* Instantiate a template alias (`template <...> using Foo = ...`).
*/
TypeAliasDecl* instantiate(ASTContext& ast, Sema& sema, DeclContext* parent,
TypeAliasTemplateDecl* decl,
ArrayRef<TemplateArgument> args) {
auto args_count = static_cast<unsigned>(args.size());
TemplateArgumentList arg_list {TemplateArgumentList::OnStack,
args.data(), args_count};
MultiLevelTemplateArgumentList multi_arg_list {arg_list};
TemplateDeclInstantiator instantiator {sema, parent, multi_arg_list};
auto instantiated = instantiator.Visit(decl);
if (auto inst_decl = dyn_cast<TypeAliasTemplateDecl>(instantiated)) {
return inst_decl->getTemplatedDecl();
}
return nullptr;
}
(pominąłem FunctionTemplateDecl, to jest poza zakresem mojego pytania.)
nie jestem całkowicie pewien, czy rozumiem, co chce zrobić, ale dlaczego nie można użyć typeid? –
@AndreiTita: Próbujemy to ocenić za pomocą parsera C++ (clang). – kennytm