Tôi đã có một giải pháp một phần, caveat duy nhất là, tôi không thể nhận std::is_same<N<4>, N<4>>::value
trở true
. Tôi cũng có thể sống với điều đó, vì tôi chỉ có thể xác định phương thức constexpr
hoạt động trên các giá trị trực tiếp. Nhưng tôi hy vọng ai đó có thể cung cấp một câu trả lời đúng cho việc này.
Tôi đã đặt giải pháp hoàn chỉnh và đầu vào được sửa đổi cho https://gist.github.com/4178490.
Tôi đã phát hiện ra rằng để thay đối số vào một lớp học mẫu và nhanh chóng nó, người ta sẽ:
- Sử dụng các đối số để biến ClassTemplateDecl vào ClassTemplateSpecializationDecl, và
- nhanh chóng chuyên môn sử dụng Sema::InstantiateClass phương pháp.
Phương thức Sema::RequireCompleteType gián tiếp gọi InstantiateClass và yêu cầu ít đầu vào hơn, vì vậy tôi gọi phương thức này thay thế. Do đó, chúng tôi sẽ viết:
/**
* 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;
}
Phương pháp này chỉ hoạt động đối với ClassTemplateDecl. Trong câu hỏi, chúng tôi cũng có một số TypeAliasTemplateDecl. Đối với điều này, tôi sẽ gọi trực tiếp số TemplateDeclInstantiator vì đây là đối tượng duy nhất biết TypeAliasTemplateDecl. Có lẽ phương pháp này cũng làm việc với ClassTemplateDecl, nhưng tôi không thể chắc chắn vì nó có vẻ không đủ công việc được thực hiện bằng cách sử dụng TemplateDeclInstantiator một mình.
/**
* 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;
}
(tôi bỏ qua FunctionTemplateDecl, nó được ra khỏi phạm vi của câu hỏi của tôi.)
Tôi không hoàn toàn chắc chắn tôi hiểu những gì bạn đang cố gắng để làm, nhưng tại sao bạn không thể sử dụng typeid? –
@AndreiTita: Chúng tôi đang cố gắng đánh giá điều này bằng trình phân tích cú pháp C++ (clang). – kennytm