Ответ 1
У меня есть частичное решение, единственное предостережение в том, что я не могу получить std::is_same<N<4>, N<4>>::value
для возврата true
. Хорошо, я могу жить с этим, поскольку я мог бы просто определить метод constexpr
, который напрямую управляет значениями. Но я надеюсь, что кто-то может дать правильный ответ для этого.
Я поставил полное решение и измененный ввод https://gist.github.com/4178490.
Я обнаружил, что для замены аргументов в шаблон класса и его экземпляра можно было бы:
- Используйте аргументы, чтобы включить ClassTemplateDecl в ClassTemplateSpecializationDecl и
- Активируйте специализацию с помощью метода Sema:: InstantiateClass.
Метод Sema:: RequireCompleteType косвенно вызывает InstantiateClass и требует меньше ввода, поэтому вместо этого я вызываю этот метод. Поэтому мы будем писать:
/**
* 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;
}
Этот метод работает только для ClassTemplateDecl. В этом вопросе мы также имеем TypeAliasTemplateDecl. Для этого я буду напрямую ссылаться на TemplateDeclInstantiator, так как это единственный объект, который знает TypeAliasTemplateDecl. Возможно, этот метод также работает с ClassTemplateDecl, но я не могу быть уверен, поскольку, как кажется, недостаточно работы выполняется с использованием только 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;
}
(я пропустил FunctionTemplateDecl, это выходит за рамки моего вопроса.)