首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >libclang能解析CRTP模式吗?

libclang能解析CRTP模式吗?
EN

Stack Overflow用户
提问于 2017-03-14 19:57:15
回答 1查看 657关注 0票数 3

我试图使用libclang解析C++,但它似乎与CRTP模式有问题,即当类继承自用派生类实例化的模板时:

代码语言:javascript
复制
// The Curiously Recurring Template Pattern (CRTP)
template<class T>
class Base
{
  // methods within Base can use template to access members of Derived
};

class Derived : public Base<Derived>
{
  // ...
};

我想让libclang找到游标类型CXCursor_CXXBaseSpecifier,但它只给出了CXCursor_ClassDecl类型。

如果Base不是模板类,libclang将找到CXCursor_CXXBaseSpecifier。

我想要完成的是找到继承自Base的类,但是当libclang只提供ClassDecl类时是不可能的。“公共基础”不提供游标,它似乎被忽略了。

有人知道怎么解决这个问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-18 06:55:47

具有某种CXX_BASE_SPECIFIER的游标将具有子游标,允许您确定此信息。在基本说明符引用模板类的情况下,它将有两个(同类) TEMPLATE_REF和TYPE_REF子节点。您可以在TEMPLATE_REF节点中使用该信息与类模板游标进行比较。

为了更清楚地说明这一点,我将举一个小例子。漂亮地打印以下AST的(libclang)版本:

代码语言:javascript
复制
template<class T>
class Base { };
class X1 : public Base<X1> {};
class Y1 {};
class X2 : public Y1 {};

给予:

代码语言:javascript
复制
TRANSLATION_UNIT tmp.cpp
  +--CLASS_TEMPLATE Base
  |  +--TEMPLATE_TYPE_PARAMETER T
  +--CLASS_DECL X1
  |  +--CXX_BASE_SPECIFIER Base<class X1>
  |     +--TEMPLATE_REF Base
  |     +--TYPE_REF class X1
  +--CLASS_DECL Y1
  +--CLASS_DECL X2
     +--CXX_BASE_SPECIFIER class Y1
        +--TYPE_REF class Y1

因此,一个基本的方法是:

  1. 每堂课
  2. 找到所有有CXX_BASE_SPECIFIER类型的孩子
  3. 对于基节点,查找所有这些节点都有两个子节点(其中一个具有TEMPLATE_REF类型)
  4. 对于TEMPLATE_REF节点,检查它们是否具有感兴趣的类模板的公共定义。

考虑到这将是C/C++中非常大的一段代码(用于堆栈溢出),我将介绍实现这些步骤的Python 2版本,这应该相当容易翻译。

代码语言:javascript
复制
import clang
from clang.cindex import CursorKind


def find_template_class(name):
    for c in tu.cursor.walk_preorder():
        if (c.kind == CursorKind.CLASS_TEMPLATE) and (c.spelling == name):
            return c

def inherits_from_template_class(node, base):
    for c in node.get_children():
        if c.kind != CursorKind.CXX_BASE_SPECIFIER:
            continue
        children = list(c.get_children())
        if len(children) != 2:
            continue
        if children[0].kind != CursorKind.TEMPLATE_REF:
            continue
        ctd = children[0].get_definition()
        if ctd == base:
            return True
    return False

idx = clang.cindex.Index.create()
tu = idx.parse('tmp.cpp', unsaved_files=[('tmp.cpp', s)],  args='-xc++'.split())
base = find_template_class('Base')
for c in tu.cursor.walk_preorder():
    if CursorKind.CLASS_DECL != c.kind:
        continue
    if inherits_from_template_class(c, base):
        print c.spelling
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42795408

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档