2

我有下一个使用 gcc 编译的示例代码(4.7.2 使用 -std=c++11):

template<class C>
struct template_test
{
    C testing() const
    {
        return C();
    }
};

class A;

struct test : public template_test<A> // (1)
{};

struct A
{};

int main()
{
    test t;
}

在点 (1) 处,函数template_test<A>::testing()被实例化,并使用 的函数A,特别是其默认构造函数。因此,test包含这个实例化的函数作为函数成员。但是,此时A是不完整类型,C++ 禁止使用不完整类型的成员。

这是positivegcc 的错误还是有其他解释?

4

3 回答 3

4

不仅 template_test::testing() 没有在 (1) 处实例化,它也从未在这个程序中实例化。模板成员仅在使用时被实例化,而 testing() 不被使用。为了使这一点更清楚,将代码稍微更改为:

template<class C>
struct template_test
{
    C testing() const
    {
        return C::foo();
    }
};

class A;

struct test : public template_test<A> // (1)
{};

struct A
{};

int main()
{
    test t;
}

它也可以编译并运行良好。

于 2013-02-11T20:43:41.927 回答
2

没关系。在testing()您实际调用它之前,成员函数不会被实例化。要看到这一点,请尝试将其重写如下:

C testing() const
{
    static_assert(C::value, "Error!");
    return C();
}

您会看到在您尝试调用该函数之前不会发出编译错误,但是当您添加t.testing()到您的main()函数时会触发静态断言。

换句话说,您“在第 (1) 点template_test<A>::testing()实例化函数”的前提是不正确的。

于 2013-02-11T20:38:26.470 回答
1

您正在实例化具有不完整类型的模板,这没关系。

成员函数testing返回一个不完整类型的实例,这是正确的(但是否正确只有在实例化时才会讨论)。但是,您永远不会调用该函数,因此它永远不会被实例化,因此不会出现错误。单独实例化结构(并调用其构造函数/析构函数)是无害的。

因此,GCC 让您编译它是正确的。当您尝试调用时,它会失败testing

于 2013-02-11T20:40:15.347 回答