这段代码必须有效吗?

时间:2013-02-11 20:32:56

标签: c++ templates forward-declaration

我有下一个使用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 ++禁止您使用不完整类型的成员。

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

3 个答案:

答案 0 :(得分:4)

不仅在(1)中实例化template_test :: testing(),而且在此程序中从未实例化。模板成员仅在使用时实例化,并且不使用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;
}

也编译并运行良好。

答案 1 :(得分:2)

没关系。在您实际调用它之前,testing()成员函数不会被实例化。要查看此内容,请尝试按如下方式重写:

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

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

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

答案 2 :(得分:1)

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

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

因此,GCC让你编译它是正确的。尝试拨打testing时,它会失败。