简单的正向声明使用 g++ 编译,但不使用 clang 进行编译

Simple forward declaration compiles with g++ but not clang

提问人:River 提问时间:10/26/2023 最后编辑:River 更新时间:10/26/2023 访问量:70

问:

对于一个最小可重现的例子,假设我在头文件中定义了以下类:Aa.h

// file a.h
#include <cstdio>

class A {
private:
    int val;
public:
    A(int aVal) { val = aVal; }
    int getVal() { return val; }
};

此外,我还通过标头和源代码定义了一个类Containercontainer.hcontainer.cpp

页眉:

// file container.h
#include <cstdlib>
#include <new>

class A;

class Container {
private:
    unsigned int size = 0;
    A *data = nullptr;
public:
    Container();
    Container(int size);
    ~Container();

    A getElement(unsigned int pos); 

    template <typename... Args>
    void emplace(unsigned int pos, const Args & ...args);
};

template <typename... Args>
void Container::emplace(unsigned int pos, const Args & ...args)
{
    new(data + pos) A(args...);
}

源:

// file container.cpp
#include "container.h"
#include "a.h"

Container::Container() {}

Container::Container(int size)
{
    data = static_cast<A*>(malloc(sizeof(A) * size));
}

Container::~Container()
{
    free(data);
    data = nullptr;
}

A Container::getElement(unsigned int pos)
{
    return data[pos];
}

对于测试,我使用以下命令:main.cpp

#include "a.h"
#include "container.h"


int main()
{
    A a(11);
    Container c(1);
    c.emplace(0, a);
    printf("%i\n", c.getElement(0).getVal()); // should print '11' to the console
    return 0;
}

当尝试编译和运行代码时,一切都适用于 g++(使用版本 8 到 12 进行测试)。但是 clang 抛出了错误:

In file included from container.cpp:1:
./container.h:27:11: error: arithmetic on a pointer to an incomplete type 'A'
new(data + pos) A(args...);
            ~~~~ ^
./container.h:7:7: note: forward declaration of 'A'
class A;
      ^
./container.h:27:18: error: allocation of incomplete type 'A'
new(data + pos) A(args...);
                        ^
./container.h:7:7: note: forward declaration of 'A'
class A;
      ^
2 errors generated.

可能发生了什么?这也许是一个叮叮当当的虫子吗?该代码不仅可以编译,而且可以在我在此处包含的最小版本以及我的真实代码中更复杂的版本中与 g++ 完美配合。因此,这不仅仅是“g++ 在没有警告的情况下编译损坏的东西”。

请注意,我确实发现了之前的几个问题,这些问题涉及类似但不同的问题。例如,问题 Nested classes with forward declaration cause an error in clang++, but pass without warning on g++ 似乎也发现了 clang 的正向声明的问题,但那里的讨论是专门针对嵌套类和命名空间的。另一个例子是关于 std::vector 中不完整类型的问题 Confusion(或 Clang bug?),在存在正向声明的情况下,clang 也给出了奇怪的行为。但问题与指定/不指定默认构造函数的细微差异有关。第三个例子是问题:如果在模板化函数中使用了不完整的类型,则代码使用 g++ 而不是 clang++ 进行编译,但这与格式错误的模板有关,即“由于不依赖于模板参数的构造,紧随其定义之后的模板的假设实例化将格式不正确”的问题。

因此,我在这里提出的问题可能与这些有关,但它更通用,并且精简到基础知识 - 说明一个更普遍的问题,即仅以 clang 显示的前向声明问题。

因此,我的问题是:有没有办法改变我上面的代码(当然,仍然使用类 in 而不是 include within 的前向声明)可以同时满足 clang 和 g++?Acontainer.ha.hcontainer.h

C 编译器错误 g clang++ 正向声明

评论


答: 暂无答案