有没有办法在C ++中禁止指针比较?

时间:2014-11-03 20:33:27

标签: c++ pointers equality

我有一个(工作)代码库,我希望在类层次结构中添加类似is_equivalent成员的内容。分散在整个代码库中的是比较,如

if (foo == bar) ...

其中foobar是类层次结构中对象的普通指针。我想介绍如下的用法(作为基类中的虚函数):

if (foo->is_equivalent(bar)) ...

这样就可以放松“平等”的概念。一个具体的几何示例可能是一个形状层次结构,其中Circle应该被认为等同于具有相等长轴和短轴的Ellipse(不是完美的类比)。

我想做的是让编译器帮助我找到我已经完成直接指针比较的所有实例。我有一个想法是提供类似operator==(const Shape *, const Shape *)的东西,但C ++甚至不允许这样做。

某些指针比较可能需要保持指针比较,但有些需要更改为虚拟方法调用。我需要看看每一个。有哪些方法可以识别所有这些类型的比较?暂时中断构建或执行是好的。有很好的测试覆盖率。

我已经阅读了类似的问题C++ Trick to avoid pointer comparison,但更为有限,因为接受的答案假定存在工厂类。

1 个答案:

答案 0 :(得分:5)

您可以编写自定义代码分析工具。这是我使用libclang构建的最小(而且相当简单)的示例。这会过滤掉源中的每个二元运算符。通过改进它,您可以从AST收集所有指针相等比较。

#include <clang-c/Index.h>
#include <stdio.h>

static void printBinOp(CXCursor cursor)
{
    CXSourceRange range = clang_getCursorExtent(cursor);
    CXSourceLocation begin = clang_getRangeStart(range);
    CXSourceLocation end = clang_getRangeEnd(range);
    CXFile file;
    unsigned begin_offset, end_offset, length;

    // retrieve physical location of AST node
    clang_getSpellingLocation(begin, &file, NULL, NULL, &begin_offset);
    clang_getSpellingLocation(end, NULL, NULL, NULL, &end_offset);
    length = end_offset - begin_offset;

    // Open the file, error checking omitted for clarity
    CXString xfname = clang_getFileName(file);
    const char *fname = clang_getCString(xfname);
    FILE *fhndl = fopen(fname, "r");
    clang_disposeString(xfname);

    // Read the source
    char buf[length + 1];
    fseek(fhndl, begin_offset, SEEK_SET);
    fread(buf, length, 1, fhndl);
    buf[length] = 0;
    fclose(fhndl);

    // and print it
    printf("Comparison: %s\n", buf);
}

static enum CXChildVisitResult ptrCompVisitor(CXCursor cursor, CXCursor parent, CXClientData client_data)
{
    if (clang_getCursorKind(cursor) == CXCursor_BinaryOperator) {
        printBinOp(cursor);
    }

    return CXChildVisit_Recurse;
}

int main()
{
    CXIndex index = clang_createIndex(0, 0);
    CXTranslationUnit tu = clang_parseTranslationUnit(index, "foo.cpp", NULL, 0, NULL, 0, CXTranslationUnit_None);

    clang_visitChildren(clang_getTranslationUnitCursor(tu), ptrCompVisitor, NULL);

    clang_disposeTranslationUnit(tu);
    clang_disposeIndex(index);
    return 0;
}

我使用的示例文件是这个虚构的C ++源文件(名为foo.cpp):

class Foo {
    int foo;
};

class Bar {
    int bar;
}

int main()
{
    void *f = new Foo();
    void *b = new Bar();

    bool alwaystrue_1 = f == f;
    bool alwaystrue_2 = b == b;

    return f == b;
}

我的工具打印了这个:

Comparison: f == f
Comparison: b == b
Comparison: f == b