如何在clang库中执行模板替换
How to perform template substitution in the clang library?
具体来说,我们有一个C++源文件,如下所示:
template <int n>
struct N {};
struct B {
template <typename M>
using A = typename std::conditional<std::is_same<M, N<4>>::value,
int*, void*>::type;
};
template <typename T, T value>
struct F : B {};
template <>
struct F<decltype(&fopen), &fopen> : B {
template <typename M>
using A = double*;
};
template <>
struct F<decltype(&fclose), &fclose> : B {
template <typename M>
using A = typename std::conditional<std::is_same<M, N<16>>::value,
void*, char**>::type;
};
// More specialization of 'F' follows.
很容易找到N
和F
的ClassTemplateDecls,以及函数指针&fopen
、&fclose
等的QualType和FunctionDecl。但问题是如何在不修改源代码的情况下将这些参数替换为N、F和F::A。
问题是:
- 如何评估
F<decltype(&fprintf), &fprintf>::A<N<4>>
并知道它是int*
- 如何评估
F<decltype(&fopen), &fopen>::A<N<7>>
并知道它是double*
- 等等
我有一个部分解决方案,唯一需要注意的是,我不能让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,它超出了我的问题范围。)
相关文章:
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- 模板参数替换失败,并且未完成隐式转换
- C++,系统无法执行指定的程序
- 使用C++中的模板和运算符重载执行矩阵运算
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 执行函数时导致崩溃的变量
- 无论条件是否为true,if总是在c++中执行
- 如何用转义符替换字符串中的所有特殊字符
- 当函数模板参数是具有默认参数的类模板时,函数模板参数的推导如何执行
- 如何用共享库替换可执行C++程序的功能?
- 如果在执行过程中替换二进制文件,"const"数组是否驻留在内存中?
- 对 std::string 执行正则表达式搜索和替换
- 替换decorator模式以强制执行创建顺序
- 如何在clang库中执行模板替换
- 当可执行文件在执行过程中被替换时如何处理"/proc/self/exe"的readlink()?
- 如果可变参数包为空,则对可变参数包类型执行替换
- 如何在替换调用方并在 xp/vista/7 上运行的窗口中从我的 VS2008/C++ 应用程序执行程序
- 将 const 无符号字符* 分配给执行就地替换或省略的 std::string
- 内联函数体的替换何时执行?
- 如何在复杂情况下执行宏替换